diff --git a/src/js/app-controller.js b/src/js/app-controller.js index f03e0e2..9730118 100644 --- a/src/js/app-controller.js +++ b/src/js/app-controller.js @@ -17,6 +17,7 @@ define(function(require) { OutboxBO = require('js/bo/outbox'), PGP = require('js/crypto/pgp'), PgpBuilder = require('pgpbuilder'), + UpdateHandler = require('js/util/update/update-handler'), config = require('js/app-config').config; var self = {}; @@ -334,23 +335,24 @@ define(function(require) { }; self.buildModules = function() { - var lawnchairDao, restDao, pubkeyDao, invitationDao, - emailDao, keychain, pgp, userStorage, pgpbuilder; + var lawnchairDao, restDao, pubkeyDao, emailDao, keychain, pgp, devicestorage, pgpbuilder; + // start the mailreader's worker thread mailreader.startWorker(config.workerPath + '/../lib/mailreader-parser-worker.js'); // init objects and inject dependencies restDao = new RestDAO(); pubkeyDao = new PublicKeyDAO(restDao); lawnchairDao = new LawnchairDAO(); - userStorage = new DeviceStorageDAO(lawnchairDao); - self._invitationDao = invitationDao = new InvitationDAO(restDao); + self._devicestorage = devicestorage = new DeviceStorageDAO(lawnchairDao); + self._invitationDao = new InvitationDAO(restDao); self._keychain = keychain = new KeychainDAO(lawnchairDao, pubkeyDao); self._crypto = pgp = new PGP(); self._pgpbuilder = pgpbuilder = new PgpBuilder(); - self._emailDao = emailDao = new EmailDAO(keychain, pgp, userStorage, pgpbuilder, mailreader); - self._outboxBo = new OutboxBO(emailDao, keychain, userStorage); + self._emailDao = emailDao = new EmailDAO(keychain, pgp, devicestorage, pgpbuilder, mailreader); + self._outboxBo = new OutboxBO(emailDao, keychain, devicestorage); + self._updateHandler = new UpdateHandler(self._appConfigStore, devicestorage); }; /** @@ -359,30 +361,48 @@ define(function(require) { self.init = function(options, callback) { self.buildModules(); - // init email dao - var account = { - emailAddress: options.emailAddress, - asymKeySize: config.asymKeySize - }; + // init user's local database + self._devicestorage.init(options.emailAddress, function() { - self._emailDao.init({ - account: account - }, function(err, keypair) { + // Migrate the databases if necessary + self._updateHandler.update(onUpdate); + }); + + function onUpdate(err) { if (err) { - callback(err); + callback({ + errMsg: 'Update failed, please reinstall the app.', + err: err + }); return; } - // connect tcp clients on first startup - self.onConnect(function(err) { + // account information for the email dao + var account = { + emailAddress: options.emailAddress, + asymKeySize: config.asymKeySize + }; + + // init email dao + self._emailDao.init({ + account: account + }, function(err, keypair) { if (err) { callback(err); return; } - callback(null, keypair); + // connect tcp clients on first startup + self.onConnect(function(err) { + if (err) { + callback(err); + return; + } + + callback(null, keypair); + }); }); - }); + } }; return self; diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index b6668a5..d42bef6 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -39,18 +39,15 @@ define(function(require) { initKeychain(); function initKeychain() { - // init user's local database - self._devicestorage.init(emailAddress, function() { - // call getUserKeyPair to read/sync keypair with devicestorage/cloud - self._keychain.getUserKeyPair(emailAddress, function(err, storedKeypair) { - if (err) { - callback(err); - return; - } + // call getUserKeyPair to read/sync keypair with devicestorage/cloud + self._keychain.getUserKeyPair(emailAddress, function(err, storedKeypair) { + if (err) { + callback(err); + return; + } - keypair = storedKeypair; - initFolders(); - }); + keypair = storedKeypair; + initFolders(); }); } diff --git a/test/new-unit/app-controller-test.js b/test/new-unit/app-controller-test.js index d25e789..6d25762 100644 --- a/test/new-unit/app-controller-test.js +++ b/test/new-unit/app-controller-test.js @@ -5,19 +5,19 @@ define(function(require) { EmailDAO = require('js/dao/email-dao'), OutboxBO = require('js/bo/outbox'), DeviceStorageDAO = require('js/dao/devicestorage-dao'), + UpdateHandler = require('js/util/update/update-handler'), expect = chai.expect; describe('App Controller unit tests', function() { - var emailDaoStub, outboxStub, appConfigStoreStub, isOnlineStub, + var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, identityStub; beforeEach(function() { - emailDaoStub = sinon.createStubInstance(EmailDAO); - controller._emailDao = emailDaoStub; - outboxStub = sinon.createStubInstance(OutboxBO); - controller._outboxBo = outboxStub; - appConfigStoreStub = sinon.createStubInstance(DeviceStorageDAO); - controller._appConfigStore = appConfigStoreStub; + controller._emailDao = emailDaoStub = sinon.createStubInstance(EmailDAO); + controller._outboxBo = outboxStub = sinon.createStubInstance(OutboxBO); + controller._appConfigStore = appConfigStoreStub = sinon.createStubInstance(DeviceStorageDAO); + controller._devicestorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); + controller._updateHandler = updateHandlerStub = sinon.createStubInstance(UpdateHandler); isOnlineStub = sinon.stub(controller, 'isOnline'); @@ -226,9 +226,11 @@ define(function(require) { }); describe('init', function() { - var buildModulesStub, onConnectStub; + var buildModulesStub, onConnectStub, emailAddress; beforeEach(function() { + emailAddress = 'alice@bob.com'; + // buildModules buildModulesStub = sinon.stub(controller, 'buildModules'); buildModulesStub.returns(); @@ -241,42 +243,70 @@ define(function(require) { onConnectStub.restore(); }); + it('should fail due to error in update handler', function(done) { + devicestorageStub.init.yields(); + updateHandlerStub.update.yields({}); + + controller.init({}, function(err, keypair) { + expect(err).to.exist; + expect(keypair).to.not.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; + done(); + }); + }); + it('should fail due to error in emailDao.init', function(done) { + devicestorageStub.init.yields(); + updateHandlerStub.update.yields(); emailDaoStub.init.yields({}); controller.init({}, function(err, keypair) { expect(err).to.exist; expect(keypair).to.not.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(emailDaoStub.init.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; done(); }); }); it('should fail due to error in onConnect', function(done) { + devicestorageStub.init.yields(); + updateHandlerStub.update.yields(); emailDaoStub.init.yields(); onConnectStub.yields({}); controller.init({}, function(err) { expect(err).to.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(emailDaoStub.init.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; expect(onConnectStub.calledOnce).to.be.true; done(); }); }); it('should work and return a keypair', function(done) { + devicestorageStub.init.withArgs(emailAddress).yields(); emailDaoStub.init.yields(null, {}); + updateHandlerStub.update.yields(); onConnectStub.yields(); - controller.init({}, function(err, keypair) { + controller.init({ + emailAddress: emailAddress + }, function(err, keypair) { expect(err).to.not.exist; expect(keypair).to.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(emailDaoStub.init.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; expect(onConnectStub.calledOnce).to.be.true; done(); }); }); }); - }); - }); \ No newline at end of file diff --git a/test/new-unit/email-dao-test.js b/test/new-unit/email-dao-test.js index 6cc7780..6648e76 100644 --- a/test/new-unit/email-dao-test.js +++ b/test/new-unit/email-dao-test.js @@ -177,7 +177,6 @@ define(function(require) { folders = [{}, {}]; // initKeychain - devicestorageStub.init.withArgs(emailAddress).yields(); keychainStub.getUserKeyPair.yields(null, mockKeyPair); // initFolders @@ -194,7 +193,6 @@ define(function(require) { expect(dao._account).to.equal(account); expect(dao._account.folders).to.equal(folders); - expect(devicestorageStub.init.calledOnce).to.be.true; expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; expect(listFolderStub.calledOnce).to.be.true; @@ -207,7 +205,6 @@ define(function(require) { var listFolderStub; // initKeychain - devicestorageStub.init.withArgs(emailAddress).yields(); keychainStub.getUserKeyPair.yields(null, mockKeyPair); // initFolders @@ -226,7 +223,6 @@ define(function(require) { expect(dao._account).to.equal(account); expect(dao._account.folders).to.equal(undefined); - expect(devicestorageStub.init.calledOnce).to.be.true; expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; expect(listFolderStub.calledOnce).to.be.true; @@ -238,7 +234,6 @@ define(function(require) { var listFolderStub; // initKeychain - devicestorageStub.init.withArgs(emailAddress).yields(); keychainStub.getUserKeyPair.yields(null, mockKeyPair); // initFolders @@ -252,7 +247,6 @@ define(function(require) { expect(keyPair).to.not.exist; expect(dao._account).to.equal(account); - expect(devicestorageStub.init.calledOnce).to.be.true; expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; expect(listFolderStub.calledOnce).to.be.true; @@ -261,7 +255,6 @@ define(function(require) { }); it('should fail due to error in getUserKeyPair', function(done) { - devicestorageStub.init.yields(); keychainStub.getUserKeyPair.yields({}); dao.init({ @@ -270,8 +263,6 @@ define(function(require) { expect(err).to.exist; expect(keyPair).to.not.exist; - expect(devicestorageStub.init.calledOnce).to.be.true; - done(); }); });