diff --git a/src/js/app-controller.js b/src/js/app-controller.js index 95c7a84..272ed5b 100644 --- a/src/js/app-controller.js +++ b/src/js/app-controller.js @@ -36,36 +36,66 @@ define(function(require) { } }; + /** + * Request an OAuth token from chrome for gmail users + */ self.fetchOAuthToken = function(password, callback) { // get OAuth Token from chrome chrome.identity.getAuthToken({ 'interactive': true }, function(token) { - // fetch gmail user's email address from the Google Authorization Server endpoint - $.ajax({ - url: 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + token, - type: 'GET', - dataType: 'json', - success: function(info) { - // login using the received email address - self.login(info.email, password, token, function(err) { - // send email address to sandbox - callback(err, info.email); - }); - }, - error: function(xhr, textStatus, err) { + if (!token) { + callback({ + errMsg: 'Error fetching an OAuth token for the user!' + }); + return; + } + + // get email address for the token + self.queryEmailAddress(token, function(err, emailAddress) { + if (err || !emailAddress) { callback({ - errMsg: xhr.status + ': ' + xhr.statusText, + errMsg: 'Error looking up email address on login!', err: err }); + return; } - }); + // login using the received email address + self.login(emailAddress, password, token, function(err) { + // send email address to sandbox + callback(err, emailAddress); + }); + }); } ); }; + /** + * Lookup the user's email address. Check local cache if available, otherwise query google's token info api to learn the user's email address + */ + self.queryEmailAddress = function(token, callback) { + // fetch gmail user's email address from the Google Authorization Server endpoint + $.ajax({ + url: 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + token, + type: 'GET', + dataType: 'json', + success: function(info) { + callback(null, info.email); + }, + error: function(xhr, textStatus, err) { + callback({ + errMsg: xhr.status + ': ' + xhr.statusText, + err: err + }); + } + }); + }; + + /** + * Instanciate the mail email data access object and its dependencies. Login to imap on init. + */ self.login = function(userId, password, token, callback) { var auth, imapOptions, smtpOptions, keychain, imapClient, smtpClient, crypto, deviceStorage; diff --git a/src/js/dao/devicestorage-dao.js b/src/js/dao/devicestorage-dao.js index 24fd2f5..5f2c9cd 100644 --- a/src/js/dao/devicestorage-dao.js +++ b/src/js/dao/devicestorage-dao.js @@ -23,25 +23,35 @@ define(function(require) { * @param list [Array] The list of items to be persisted * @param type [String] The type of item to be persisted e.g. 'email' */ - DeviceStorageDAO.prototype.storeEcryptedList = function(list, type, callback) { + DeviceStorageDAO.prototype.storeList = function(list, type, callback) { var date, key, items = []; // nothing to store - if (list.length === 0) { + if (!list || list.length === 0) { callback(); return; } + // validate type + if (!type) { + callback({ + errMsg: 'Type is not set!' + }); + return; + } + // format items for batch storing in dao list.forEach(function(i) { // put uid in key if available... for easy querying if (i.uid) { key = type + '_' + i.uid; - } else if (i.sentDate) { + } else if (i.sentDate && i.id) { date = util.parseDate(i.sentDate); key = type + '_' + i.sentDate + '_' + i.id; - } else { + } else if (i.id) { key = type + '_' + i.id; + } else { + key = type; } items.push({ @@ -61,7 +71,7 @@ define(function(require) { * @param offset [Number] The offset of items to fetch (0 is the last stored item) * @param num [Number] The number of items to fetch (null means fetch all) */ - DeviceStorageDAO.prototype.listEncryptedItems = function(type, offset, num, callback) { + DeviceStorageDAO.prototype.listItems = function(type, offset, num, callback) { // fetch all items of a certain type from the data-store jsonDao.list(type, offset, num, function(encryptedList) { diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index fb22578..6748407 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -314,7 +314,7 @@ define(function(require) { } // fetch items from device storage - self._devicestorage.listEncryptedItems('email_' + options.folder, options.offset, options.num, function(err, emails) { + self._devicestorage.listItems('email_' + options.folder, options.offset, options.num, function(err, emails) { if (err) { callback(err); return; @@ -412,7 +412,7 @@ define(function(require) { fetchList(options, function(emails) { // persist encrypted list in device storage - self._devicestorage.storeEcryptedList(emails, 'email_' + options.folder, function() { + self._devicestorage.storeList(emails, 'email_' + options.folder, function() { callback(); }); }); diff --git a/test/new-unit/email-dao-test.js b/test/new-unit/email-dao-test.js index 4283d8f..e368952 100644 --- a/test/new-unit/email-dao-test.js +++ b/test/new-unit/email-dao-test.js @@ -371,7 +371,7 @@ define(function(require) { imapClientStub.getMessage.yields(null, { body: 'asdf' }); - devicestorageStub.storeEcryptedList.yields(); + devicestorageStub.storeList.yields(); emailDao.imapSync({ folder: 'INBOX', @@ -381,7 +381,7 @@ define(function(require) { expect(err).to.not.exist; expect(imapClientStub.listMessages.calledOnce).to.be.true; expect(imapClientStub.getMessage.calledTwice).to.be.true; - expect(devicestorageStub.storeEcryptedList.calledOnce).to.be.true; + expect(devicestorageStub.storeList.calledOnce).to.be.true; done(); }); }); @@ -390,7 +390,7 @@ define(function(require) { describe('IMAP: list messages from local storage', function() { it('should work', function(done) { - devicestorageStub.listEncryptedItems.yields(null, [{ + devicestorageStub.listItems.yields(null, [{ body: '' }]); keychainStub.getPublicKeys.yields(null, [{ @@ -405,7 +405,7 @@ define(function(require) { offset: 0, num: 2 }, function(err, emails) { - expect(devicestorageStub.listEncryptedItems.calledOnce).to.be.true; + expect(devicestorageStub.listItems.calledOnce).to.be.true; expect(keychainStub.getPublicKeys.calledOnce).to.be.true; expect(cryptoStub.decryptListForUser.calledOnce).to.be.true; expect(err).to.not.exist; diff --git a/test/unit/devicestorage-dao-test.js b/test/unit/devicestorage-dao-test.js index 5e6ace3..0cc9dbc 100644 --- a/test/unit/devicestorage-dao-test.js +++ b/test/unit/devicestorage-dao-test.js @@ -63,7 +63,7 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag }); asyncTest("Store encrypted list", 1, function() { - storage.storeEcryptedList(devicestorageTest.encryptedList, 'email_inbox', function() { + storage.storeList(devicestorageTest.encryptedList, 'email_inbox', function() { ok(true, 'Store encrypted list'); start(); @@ -78,7 +78,7 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag num = 6; // list encrypted items from storage - storage.listEncryptedItems('email_inbox', offset, num, function(err, encryptedList) { + storage.listItems('email_inbox', offset, num, function(err, encryptedList) { ok(!err); // decrypt list