Skip to content

Commit

Permalink
Merge pull request mozilla#3150 from mozilla/simplify_storage
Browse files Browse the repository at this point in the history
Simplify the storage.js interface
  • Loading branch information
jaredhirsch committed Apr 12, 2013
2 parents 687bff8 + 3f9eb30 commit 329e9ea
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 81 deletions.
81 changes: 37 additions & 44 deletions resources/static/common/js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ BrowserID.Storage = (function() {
// issues do not become a factor. See issue #2206
setDefaultValues();

// BEGIN TRANSITION CODE
/** Transition code is to handle the moving data from the .loggedIn
* namespace to the .site namespace. It can safely be removed one month after
* this is merged when people's Persona sessions have expired.
*/
function upgradeLoggedInInfo() {
var allInfo = JSON.parse(storage.loggedIn || "{}");
for (var site in allInfo) {
siteSet(site, "logged_in", allInfo[site]);
}
}
upgradeLoggedInInfo();
// END TRANSITION CODE

function storeEmails(emails) {
storage.emails = JSON.stringify(emails);
}
Expand All @@ -61,7 +75,6 @@ BrowserID.Storage = (function() {
emailToUserID: {},
emails: {},
interaction_data: {},
loggedIn: {},
main_site: {},
managePage: {},
returnTo: null,
Expand Down Expand Up @@ -117,17 +130,12 @@ BrowserID.Storage = (function() {
if(siteInfo[site].email === email) {
delete siteInfo[site].email;
}
}
storage.siteInfo = JSON.stringify(siteInfo);

// remove any logged in sites associated with this address.
var loggedInInfo = JSON.parse(storage.loggedIn || "{}");
for(var loggedSite in loggedInInfo) {
if(loggedInInfo[loggedSite] === email) {
delete loggedInInfo[loggedSite];
if (siteInfo[site].logged_in === email) {
delete siteInfo[site].logged_in;
}
}
storage.loggedIn = JSON.stringify(loggedInInfo);
storage.siteInfo = JSON.stringify(siteInfo);
}
else {
throw new Error("unknown email address");
Expand Down Expand Up @@ -228,28 +236,21 @@ BrowserID.Storage = (function() {
storage[namespace] = JSON.stringify(allInfo);
}

function setLoggedIn(origin, email) {
var allInfo = JSON.parse(storage.loggedIn || "{}");
if (email) allInfo[origin] = email;
else delete allInfo[origin];
storage.loggedIn = JSON.stringify(allInfo);
}

function getLoggedIn(origin) {
var allInfo = JSON.parse(storage.loggedIn || "{}");
return allInfo[origin];
}

function loggedInCount() {
var allInfo = JSON.parse(storage.loggedIn || "{}");
return _.size(allInfo);
var count = 0;
var allSiteInfo = JSON.parse(storage.siteInfo || "{}");
for (var key in allSiteInfo) {
if (allSiteInfo[key].logged_in) count++;
}

return count;
}

function watchLoggedIn(origin, callback) {
var lastState = getLoggedIn(origin);
var lastState = siteGet(origin, "logged_in");

function checkState() {
var currentState = getLoggedIn(origin);
var currentState = siteGet(origin, "logged_in");
if (lastState !== currentState) {
callback();
lastState = currentState;
Expand All @@ -260,8 +261,13 @@ BrowserID.Storage = (function() {
if (window.addEventListener) window.addEventListener('storage', checkState, false);
else window.setInterval(checkState, 2000);
}

function logoutEverywhere() {
storage.loggedIn = "{}";
var allSiteInfo = JSON.parse(storage.siteInfo || "{}");
for (var site in allSiteInfo) {
delete allSiteInfo[site].logged_in;
}
storage.siteInfo = JSON.stringify(allSiteInfo);
}

function mapEmailToUserID(emailOrUserID) {
Expand Down Expand Up @@ -459,6 +465,11 @@ BrowserID.Storage = (function() {
*/
invalidateEmail: invalidateEmail,

/**
* The site namespace is where to store any information that relates to
* a particular RP, like which email is selected, if an email is signed in,
* etc.
*/
site: {
/**
* Set a data field for a site
Expand Down Expand Up @@ -501,12 +512,6 @@ BrowserID.Storage = (function() {
remove: generic2KeyRemove.curry("managePage")
},

signInEmail: {
set: generic2KeySet.curry("main_site", "signInEmail"),
get: generic2KeyGet.curry("main_site", "signInEmail"),
remove: generic2KeyRemove.curry("main_site", "signInEmail")
},

usersComputer: {
/**
* Query whether the user has confirmed that this is their computer
Expand Down Expand Up @@ -557,18 +562,6 @@ BrowserID.Storage = (function() {
*/
updateEmailToUserIDMapping: updateEmailToUserIDMapping,

/** set logged in state for a site
* @param {string} origin - the site to set logged in state for
* @param {string} email - the email that the user is logged in with or falsey if login state should be cleared
*/
setLoggedIn: setLoggedIn,

/** check if the user is logged into a site
* @param {string} origin - the site to set check the logged in state of
* @returns the email with which the user is logged in
*/
getLoggedIn: getLoggedIn,

/**
* Get the number of sites the user is logged in to.
* @method loggedInCount
Expand Down
4 changes: 2 additions & 2 deletions resources/static/common/js/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ BrowserID.User = (function() {
// might have fewer race conditions and do fewer network requests.
User.checkAuthenticationAndSync(function(authenticated) {
if (authenticated) {
var loggedInEmail = storage.getLoggedIn(origin);
var loggedInEmail = storage.site.get(origin, "logged_in");
if (loggedInEmail !== siteSpecifiedEmail) {
if (loggedInEmail) {
User.getAssertion(loggedInEmail, origin, function(assertion) {
Expand Down Expand Up @@ -1412,7 +1412,7 @@ BrowserID.User = (function() {
logout: function(onComplete, onFailure) {
User.checkAuthentication(function(authenticated) {
if (authenticated) {
storage.setLoggedIn(origin, false);
storage.site.remove(origin, "logged_in");
}

if (onComplete) {
Expand Down
2 changes: 1 addition & 1 deletion resources/static/communication_iframe/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
// logout have been called before. This allows the user to be force logged
// out.
if (loggedInUser !== null) {
storage.setLoggedIn(remoteOrigin, false);
storage.site.remove(remoteOrigin, "logged_in");
loggedInUser = null;
chan.notify({ method: 'logout' });
}
Expand Down
2 changes: 1 addition & 1 deletion resources/static/dialog/js/misc/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ BrowserID.State = (function() {
handleState("assertion_generated", function(msg, info) {
self.success = true;
if (info.assertion !== null) {
storage.setLoggedIn(user.getOrigin(), self.email);
storage.site.set(user.getOrigin(), "logged_in", self.email);

startAction("doAssertionGenerated", { assertion: info.assertion, email: self.email });
}
Expand Down
2 changes: 0 additions & 2 deletions resources/static/dialog/js/modules/generate_assertion.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ BrowserID.Modules.GenerateAssertion = (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);
}
});
Expand Down
10 changes: 6 additions & 4 deletions resources/static/pages/js/page_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@ BrowserID.PageHelpers = (function() {
helpers = bid.Helpers,
dom = bid.DOM,
ANIMATION_SPEED = 250,
origStoredEmail;
origStoredEmail,
origin = "https://login.persona.org",
storageKey = "sign_in_email";

function setStoredEmail(email) {
storage.signInEmail.set(email);
storage.site.set(origin, storageKey, email);
}

function clearStoredEmail() {
storage.signInEmail.remove();
storage.site.remove(origin, storageKey);
}

function getStoredEmail() {
return storage.signInEmail.get() || "";
return storage.site.get(origin, storageKey) || "";
}

function onEmailChange(event) {
Expand Down
3 changes: 2 additions & 1 deletion resources/static/pages/js/reset_password.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ BrowserID.resetPassword = (function() {
// closes the dialog OR if redirection happens before the dialog
// has had a chance to finish its business.
/*jshint newcap:false*/
storage.setLoggedIn(URLParse(self.redirectTo).originOnly(), self.email);
storage.site.set(URLParse(self.redirectTo).originOnly(),
"logged_in", self.email);

countdownTimeout.call(self, function() {
self.doc.location = self.redirectTo;
Expand Down
3 changes: 2 additions & 1 deletion resources/static/pages/js/verify_secondary_address.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ BrowserID.verifySecondaryAddress = (function() {
// closes the dialog OR if redirection happens before the dialog
// has had a chance to finish its business.
/*jshint newcap:false*/
storage.setLoggedIn(URLParse(self.redirectTo).originOnly(), self.email);
storage.site.set(URLParse(self.redirectTo).originOnly(),
"logged_in", self.email);

countdownTimeout.call(self, function() {
self.doc.location = self.redirectTo;
Expand Down
17 changes: 5 additions & 12 deletions resources/static/test/cases/common/js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,24 +160,17 @@
equal(storage.getReturnTo(), "http://some.domain/path", "setReturnTo/getReturnTo working as expected");
});

test("signInEmail.set/.get/.remove - set, get, and remove the signInEmail", function() {
storage.signInEmail.set("testuser@testuser.com");
equal(storage.signInEmail.get(), "testuser@testuser.com", "correct email gotten");
storage.signInEmail.remove();
equal(typeof storage.signInEmail.get(), "undefined", "after remove, signInEmail is empty");
});

test("setLoggedIn, getLoggedIn, loggedInCount", function() {
test("site.set->logged_in, site.get->logged_in, loggedInCount", function() {
var email = "testuser@testuser.com";
storage.addEmail(email, {});
storage.setLoggedIn(TEST_ORIGIN, email);
equal(storage.getLoggedIn(TEST_ORIGIN), email, "correct email");
storage.setLoggedIn("http://another.domain", email);
storage.site.set(TEST_ORIGIN, "logged_in", email);
storage.site.set("http://another.domain", "logged_in", email);

equal(storage.loggedInCount(), 2, "correct logged in count");

storage.removeEmail(email);
equal(storage.loggedInCount(), 0, "after email removed, not logged in anywhere");
testHelpers.testUndefined(storage.getLoggedIn(TEST_ORIGIN), "sites with email no longer logged in");
testHelpers.testUndefined(storage.site.get(TEST_ORIGIN, "logged_in"), "sites with email no longer logged in");
});

}());
Expand Down
4 changes: 2 additions & 2 deletions resources/static/test/cases/common/js/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@
xhr.setContextInfo("auth_level", "password");

lib.syncEmailKeypair(LOGGED_IN_EMAIL, function() {
storage.setLoggedIn(lib.getOrigin(), LOGGED_IN_EMAIL);
storage.site.set(lib.getOrigin(), "logged_in", LOGGED_IN_EMAIL);
lib.getSilentAssertion(LOGGED_IN_EMAIL, function(email, assertion) {
equal(email, LOGGED_IN_EMAIL, "correct email");
strictEqual(assertion, null, "correct assertion");
Expand All @@ -1102,7 +1102,7 @@
var REQUESTED_EMAIL = "requested@testuser.com";

lib.syncEmailKeypair(LOGGED_IN_EMAIL, function() {
storage.setLoggedIn(lib.getOrigin(), LOGGED_IN_EMAIL);
storage.site.set(lib.getOrigin(), "logged_in", LOGGED_IN_EMAIL);
lib.getSilentAssertion(REQUESTED_EMAIL, function(email, assertion) {
equal(email, LOGGED_IN_EMAIL, "correct email");
testAssertion(assertion, start);
Expand Down
18 changes: 9 additions & 9 deletions resources/static/test/cases/dialog/js/misc/internal_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
asyncTest("get with silent: true, authenticated user, no requiredEmail, email address associated with site, XHR failure - return null assertion.", function() {
user.authenticate(TEST_EMAIL, TEST_PASSWORD, function() {
user.syncEmails(function() {
storage.setLoggedIn(ORIGIN, "email", TEST_EMAIL);
storage.site.set(ORIGIN, "logged_in", TEST_EMAIL);

xhr.useResult("invalid");

Expand Down Expand Up @@ -194,16 +194,16 @@
asyncTest("logout of authenticated user logs the user out of origin", function() {
user.authenticate(TEST_EMAIL, TEST_PASSWORD, function() {
// simulate multiple origin->email associations.
storage.setLoggedIn(ORIGIN, "email", TEST_EMAIL);
storage.setLoggedIn(ORIGIN + "2", "email", TEST_EMAIL);
storage.site.set(ORIGIN, "logged_in", TEST_EMAIL);
storage.site.set(ORIGIN + "2", "logged_in", TEST_EMAIL);

internal.logout(ORIGIN, function(success) {
equal(success, true, "user has been successfully logged out");

// with logout, only the association specified for the origin is
// cleared.
testUndefined(storage.getLoggedIn(ORIGIN, "email"));
testNotUndefined(storage.getLoggedIn(ORIGIN + "2", "email"));
testUndefined(storage.site.get(ORIGIN, "logged_in"));
testNotUndefined(storage.site.get(ORIGIN + "2", "logged_in"));

start();
});
Expand All @@ -220,14 +220,14 @@
asyncTest("logoutEverywhere of authenticated user logs the user out everywhere", function() {
user.authenticate(TEST_EMAIL, TEST_PASSWORD, function() {
// simulate multiple origin->email associations.
storage.setLoggedIn(ORIGIN, "email", TEST_EMAIL);
storage.setLoggedIn(ORIGIN + "2", "email", TEST_EMAIL);
storage.site.set(ORIGIN, "logged_in", TEST_EMAIL);
storage.site.set(ORIGIN + "2", "logged_in", TEST_EMAIL);

internal.logoutEverywhere(function(success) {
equal(success, true, "user has been successfully logged out everywhere");
// with logoutEverywhere, both associations should be cleared.
testUndefined(storage.getLoggedIn(ORIGIN, "email"));
testUndefined(storage.getLoggedIn(ORIGIN + "2", "email"));
testUndefined(storage.site.get(ORIGIN, "logged_in"));
testUndefined(storage.site.get(ORIGIN + "2", "logged_in"));

start();
});
Expand Down
2 changes: 1 addition & 1 deletion resources/static/test/cases/pages/js/reset_password.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
testHasClass("body", "complete");
testElementTextEquals(".website", returnTo, "origin is set to redirect to login.persona.org");
testDocumentRedirected(doc, returnTo, "redirection occurred to correct URL");
equal(storage.getLoggedIn("https://test.domain"), "testuser@testuser.com", "logged in status set");
equal(storage.site.get("https://test.domain", "logged_in"), "testuser@testuser.com", "logged in status set");
start();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
testHasClass("body", "complete");
testElementTextEquals(".website", returnTo, "origin is set to redirect to login.persona.org");
testDocumentRedirected(doc, returnTo, "redirection occurred to correct URL");
equal(storage.getLoggedIn("https://test.domain"), "testuser@testuser.com", "logged in status set");
equal(storage.site.get("https://test.domain", "logged_in"), "testuser@testuser.com", "logged in status set");
start();
});
});
Expand Down

0 comments on commit 329e9ea

Please sign in to comment.