1
0
mirror of https://github.com/moparisthebest/mail synced 2024-11-22 17:02:17 -05:00

[WO-643] Refactor initialization workflow

* Move initialization pre-flight checks to app-controller
* Refresh cached public keys for user during incomplete setups
* Reorder redirect checks in login ctrl from most specific (pubkey + privkey) to most generic (no keys)
* Add overridePermission flag to KeychainDAO.refreshKeyForUserId to refresh w/o asking for user permission
This commit is contained in:
Felix Hammerl 2014-11-06 14:28:14 +01:00
parent 4722af1457
commit 7959be55a7
11 changed files with 281 additions and 165 deletions

View File

@ -7,8 +7,9 @@
var axe = require('axe-logger'), var axe = require('axe-logger'),
Auth = require('./bo/auth'), Auth = require('./bo/auth'),
PGP = require('./crypto/pgp'), PGP = require('./crypto/pgp'),
PgpMailer = require('pgpmailer'),
OAuth = require('./util/oauth'), OAuth = require('./util/oauth'),
PgpMailer = require('pgpmailer'),
util = require('crypto-lib').util,
PgpBuilder = require('pgpbuilder'), PgpBuilder = require('pgpbuilder'),
OutboxBO = require('./bo/outbox'), OutboxBO = require('./bo/outbox'),
mailreader = require('mailreader'), mailreader = require('mailreader'),
@ -121,29 +122,9 @@ ctrl.checkForUpdate = function() {
}; };
/** /**
* Instanciate the mail email data access object and its dependencies. Login to imap on init. * Fire up the database, retrieve the available keys for the user and initialize the email data access object
*/ */
ctrl.init = function(options, callback) { ctrl.init = function(options, callback) {
// init user's local database
ctrl._userStorage.init(options.emailAddress, function(err) {
if (err) {
callback(err);
return;
}
// Migrate the databases if necessary
ctrl._updateHandler.update(onUpdate);
});
function onUpdate(err) {
if (err) {
callback({
errMsg: 'Update failed, please reinstall the app.',
err: err
});
return;
}
// account information for the email dao // account information for the email dao
var account = { var account = {
realname: options.realname, realname: options.realname,
@ -151,16 +132,70 @@ ctrl.init = function(options, callback) {
asymKeySize: config.asymKeySize asymKeySize: config.asymKeySize
}; };
// init email dao // Pre-Flight check: don't even start to initialize stuff if the email address is not valid
ctrl._emailDao.init({ if (!util.validateEmailAddress(options.emailAddress)) {
account: account return callback(new Error('The user email address is invalid!'));
}, function(err, keypair) { }
prepareDatabase();
// Pre-Flight check: initialize and prepare user's local database
function prepareDatabase() {
ctrl._userStorage.init(options.emailAddress, function(err) {
if (err) { if (err) {
callback(err); return callback(err);
}
// Migrate the databases if necessary
ctrl._updateHandler.update(function(err) {
if (err) {
return callback(new Error('Updating the internal database failed. Please reinstall the app! Reason: ' + err.message));
}
prepareKeys();
});
});
}
// retrieve keypair fom devicestorage/cloud, refresh public key if signup was incomplete before
function prepareKeys() {
ctrl._keychain.getUserKeyPair(options.emailAddress, function(err, keys) {
if (err) {
return callback(err);
}
// this is either a first start on a new device, OR a subsequent start without completing the signup,
// since we can't differenciate those cases here, do a public key refresh because it might be outdated
if (keys && keys.publicKey && !keys.privateKey) {
ctrl._keychain.refreshKeyForUserId({
userId: options.emailAddress,
overridePermission: true
}, function(err, publicKey) {
if (err) {
return callback(err);
}
initEmailDao({
publicKey: publicKey
});
});
return; return;
} }
callback(null, keypair); // either signup was complete or no pubkey is available, so we're good here.
initEmailDao(keys);
});
}
function initEmailDao(keys) {
ctrl._emailDao.init({
account: account
}, function(err) {
if (err) {
return callback(err);
}
callback(null, keys);
}); });
} }
}; };

View File

@ -49,12 +49,26 @@ var LoginCtrl = function($scope, $location) {
} }
function redirect(availableKeys) { function redirect(availableKeys) {
// redirect if needed if (availableKeys && availableKeys.publicKey && availableKeys.privateKey) {
if (typeof availableKeys === 'undefined') { // public and private key available, try empty passphrase
// no public key available, start onboarding process appController._emailDao.unlock({
goTo('/login-initial'); keypair: availableKeys,
passphrase: undefined
}, function(err) {
if (err) {
goTo('/login-existing');
return;
}
} else if (availableKeys && !availableKeys.privateKey) { appController._auth.storeCredentials(function(err) {
if (err) {
return $scope.onError(err);
}
goTo('/desktop');
});
});
} else if (availableKeys && availableKeys.publicKey && !availableKeys.privateKey) {
// check if private key is synced // check if private key is synced
appController._keychain.requestPrivateKeyDownload({ appController._keychain.requestPrivateKeyDownload({
userId: availableKeys.publicKey.userId, userId: availableKeys.publicKey.userId,
@ -74,26 +88,9 @@ var LoginCtrl = function($scope, $location) {
// no private key, import key file // no private key, import key file
goTo('/login-new-device'); goTo('/login-new-device');
}); });
} else { } else {
// public and private key available, try empty passphrase // no public key available, start onboarding process
appController._emailDao.unlock({ goTo('/login-initial');
keypair: availableKeys,
passphrase: undefined
}, function(err) {
if (err) {
goTo('/login-existing');
return;
}
appController._auth.storeCredentials(function(err) {
if (err) {
return $scope.onError(err);
}
goTo('/desktop');
});
});
} }
} }

View File

@ -71,7 +71,9 @@ var MailListCtrl = function($scope, $routeParams) {
} }
firstSelect = false; firstSelect = false;
keychainDao.refreshKeyForUserId(email.from[0].address, onKeyRefreshed); keychainDao.refreshKeyForUserId({
userId: email.from[0].address
}, onKeyRefreshed);
function onKeyRefreshed(err) { function onKeyRefreshed(err) {
if (err) { if (err) {

View File

@ -229,7 +229,9 @@ var WriteCtrl = function($scope, $filter, $q) {
if (keychainDao) { if (keychainDao) {
// check if to address is contained in known public keys // check if to address is contained in known public keys
// when we write an email, we always need to work with the latest keys available // when we write an email, we always need to work with the latest keys available
keychainDao.refreshKeyForUserId(recipient.address, function(err, key) { keychainDao.refreshKeyForUserId({
userId: recipient.address
}, function(err, key) {
if (err) { if (err) {
$scope.onError(err); $scope.onError(err);
return; return;

View File

@ -1,7 +1,6 @@
'use strict'; 'use strict';
var util = require('crypto-lib').util, var config = require('../app-config').config,
config = require('../app-config').config,
str = require('../app-config').string; str = require('../app-config').string;
// //
@ -65,60 +64,21 @@ var EmailDAO = function(keychain, pgp, devicestorage, pgpbuilder, mailreader) {
/** /**
* Initializes the email dao: * Initializes the email dao:
* - validates the email address * - assigns _account
* - retrieves the user's key pair (if available)
* - initializes _account.folders with the content from memory * - initializes _account.folders with the content from memory
* *
* @param {Object} options.account The account
* @param {String} options.account.emailAddress The user's id * @param {String} options.account.emailAddress The user's id
* @param {String} options.account.realname The user's id
* @param {Function} callback(error, keypair) Invoked with the keypair or error information when the email dao is initialized * @param {Function} callback(error, keypair) Invoked with the keypair or error information when the email dao is initialized
*/ */
EmailDAO.prototype.init = function(options, callback) { EmailDAO.prototype.init = function(options, callback) {
var self = this, this._account = options.account;
keypair; this._account.busy = 0; // > 0 triggers the spinner
this._account.online = false;
this._account.loggingIn = false;
self._account = options.account; // init folders from memory
self._account.busy = 0; // triggers the spinner this._initFoldersFromDisk(callback);
self._account.online = false;
self._account.loggingIn = false;
// validate email address
var emailAddress = self._account.emailAddress;
if (!util.validateEmailAddress(emailAddress)) {
callback({
errMsg: 'The user email address must be specified!'
});
return;
}
// init keychain and then crypto module
initKeychain();
function initKeychain() {
// call getUserKeyPair to read/sync keypair with devicestorage/cloud
self._keychain.getUserKeyPair(emailAddress, function(err, storedKeypair) {
if (err) {
callback(err);
return;
}
keypair = storedKeypair;
initFolders();
});
}
function initFolders() {
// try init folders from memory, since imap client not initiated yet
self._initFoldersFromDisk(function(err) {
// dont handle offline case this time
if (err && err.code !== 42) {
callback(err);
return;
}
callback(null, keypair);
});
}
}; };
/** /**

View File

@ -81,11 +81,14 @@ KeychainDAO.prototype.getPublicKeys = function(ids, callback) {
/** /**
* Checks for public key updates of a given user id * Checks for public key updates of a given user id
* @param {String} userId The user id (email address) for which to check the key * @param {String} options.userId The user id (email address) for which to check the key
* @param {String} options.overridePermission (optional) Indicates if the update should happen automatically (true) or with the user being queried (false). Defaults to false
* @param {Function} callback(error, key) Invoked when the key has been updated or an error occurred * @param {Function} callback(error, key) Invoked when the key has been updated or an error occurred
*/ */
KeychainDAO.prototype.refreshKeyForUserId = function(userId, callback) { KeychainDAO.prototype.refreshKeyForUserId = function(options, callback) {
var self = this; var self = this,
userId = options.userId,
overridePermission = options.overridePermission;
// get the public key corresponding to the userId // get the public key corresponding to the userId
self.getReceiverPublicKey(userId, function(err, localKey) { self.getReceiverPublicKey(userId, function(err, localKey) {
@ -146,10 +149,18 @@ KeychainDAO.prototype.refreshKeyForUserId = function(userId, callback) {
} }
// the public key has changed, we need to ask for permission to update the key // the public key has changed, we need to ask for permission to update the key
if (overridePermission) {
// don't query the user, update the public key right away
onPermissionReceived(true);
} else {
// query the user if the public key should be updated
self.requestPermissionForKeyUpdate({ self.requestPermissionForKeyUpdate({
userId: userId, userId: userId,
newKey: newKey newKey: newKey
}, function(granted) { }, onPermissionReceived);
}
function onPermissionReceived(granted) {
if (!granted) { if (!granted) {
// permission was not given to update the key, so don't overwrite the old one! // permission was not given to update the key, so don't overwrite the old one!
callback(null, localKey); callback(null, localKey);
@ -169,8 +180,7 @@ KeychainDAO.prototype.refreshKeyForUserId = function(userId, callback) {
callback(err, err ? undefined : newKey); callback(err, err ? undefined : newKey);
}); });
}); });
}); }
}); });
} }
}; };

View File

@ -5,10 +5,12 @@ var controller = require('../../src/js/app-controller'),
OutboxBO = require('../../src/js/bo/outbox'), OutboxBO = require('../../src/js/bo/outbox'),
DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'),
UpdateHandler = require('../../src/js/util/update/update-handler'), UpdateHandler = require('../../src/js/util/update/update-handler'),
KeychainDAO = require('../../src/js/dao/keychain-dao'),
config = require('../../src/js/app-config').config,
Auth = require('../../src/js/bo/auth'); Auth = require('../../src/js/bo/auth');
describe('App Controller unit tests', function() { describe('App Controller unit tests', function() {
var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub; var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub, keychainStub;
beforeEach(function() { beforeEach(function() {
controller._emailDao = emailDaoStub = sinon.createStubInstance(EmailDAO); controller._emailDao = emailDaoStub = sinon.createStubInstance(EmailDAO);
@ -17,6 +19,7 @@ describe('App Controller unit tests', function() {
controller._userStorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); controller._userStorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO);
controller._updateHandler = updateHandlerStub = sinon.createStubInstance(UpdateHandler); controller._updateHandler = updateHandlerStub = sinon.createStubInstance(UpdateHandler);
controller._auth = authStub = sinon.createStubInstance(Auth); controller._auth = authStub = sinon.createStubInstance(Auth);
controller._keychain = keychainStub = sinon.createStubInstance(KeychainDAO);
isOnlineStub = sinon.stub(controller, 'isOnline'); isOnlineStub = sinon.stub(controller, 'isOnline');
}); });
@ -133,10 +136,13 @@ describe('App Controller unit tests', function() {
}); });
describe('init', function() { describe('init', function() {
var onConnectStub, emailAddress; var onConnectStub, emailAddress, keysWithPubKey;
beforeEach(function() { beforeEach(function() {
emailAddress = 'alice@bob.com'; emailAddress = 'alice@bob.com';
keysWithPubKey = {
publicKey: {}
};
// onConnect // onConnect
onConnectStub = sinon.stub(controller, 'onConnect'); onConnectStub = sinon.stub(controller, 'onConnect');
@ -146,10 +152,22 @@ describe('App Controller unit tests', function() {
onConnectStub.restore(); onConnectStub.restore();
}); });
it('should fail due to error in storage initialization', function(done) { it('should fail due to malformed email address', function(done) {
devicestorageStub.init.withArgs(undefined).yields({}); controller.init({
emailAddress: 'ishallfail'
}, function(err, keypair) {
expect(err).to.exist;
expect(keypair).to.not.exist;
done();
});
});
controller.init({}, function(err, keypair) { it('should fail due to error in storage initialization', function(done) {
devicestorageStub.init.withArgs(emailAddress).yields(new Error());
controller.init({
emailAddress: emailAddress
}, function(err, keypair) {
expect(err).to.exist; expect(err).to.exist;
expect(keypair).to.not.exist; expect(keypair).to.not.exist;
expect(devicestorageStub.init.calledOnce).to.be.true; expect(devicestorageStub.init.calledOnce).to.be.true;
@ -160,7 +178,7 @@ describe('App Controller unit tests', function() {
it('should fail due to error in update handler', function(done) { it('should fail due to error in update handler', function(done) {
devicestorageStub.init.yields(); devicestorageStub.init.yields();
updateHandlerStub.update.yields({}); updateHandlerStub.update.yields(new Error());
controller.init({ controller.init({
emailAddress: emailAddress emailAddress: emailAddress
@ -173,10 +191,48 @@ describe('App Controller unit tests', function() {
}); });
}); });
it('should fail due to error in getUserKeyPair', function(done) {
devicestorageStub.init.yields();
updateHandlerStub.update.yields();
keychainStub.getUserKeyPair.yields(new Error());
controller.init({
emailAddress: emailAddress
}, 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;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
done();
});
});
it('should fail due to error in refreshKeyForUserId', function(done) {
devicestorageStub.init.yields();
updateHandlerStub.update.yields();
keychainStub.getUserKeyPair.yields(null, keysWithPubKey);
keychainStub.refreshKeyForUserId.yields(new Error());
controller.init({
emailAddress: emailAddress
}, 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;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
expect(keychainStub.refreshKeyForUserId.calledOnce).to.be.true;
done();
});
});
it('should fail due to error in emailDao.init', function(done) { it('should fail due to error in emailDao.init', function(done) {
devicestorageStub.init.yields(); devicestorageStub.init.yields();
updateHandlerStub.update.yields(); updateHandlerStub.update.yields();
emailDaoStub.init.yields({}); keychainStub.getUserKeyPair.yields(null, keysWithPubKey);
keychainStub.refreshKeyForUserId.yields();
emailDaoStub.init.yields(new Error());
controller.init({ controller.init({
emailAddress: emailAddress emailAddress: emailAddress
@ -184,25 +240,41 @@ describe('App Controller unit tests', function() {
expect(err).to.exist; expect(err).to.exist;
expect(keypair).to.not.exist; expect(keypair).to.not.exist;
expect(updateHandlerStub.update.calledOnce).to.be.true; expect(updateHandlerStub.update.calledOnce).to.be.true;
expect(emailDaoStub.init.calledOnce).to.be.true;
expect(devicestorageStub.init.calledOnce).to.be.true; expect(devicestorageStub.init.calledOnce).to.be.true;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
expect(keychainStub.refreshKeyForUserId.calledOnce).to.be.true;
expect(emailDaoStub.init.calledOnce).to.be.true;
done(); done();
}); });
}); });
it('should work and return a keypair', function(done) { it('should work and not return a keypair', function(done) {
devicestorageStub.init.withArgs(emailAddress).yields(); devicestorageStub.init.withArgs(emailAddress).yields();
emailDaoStub.init.yields(null, {});
updateHandlerStub.update.yields(); updateHandlerStub.update.yields();
keychainStub.getUserKeyPair.withArgs(emailAddress).yields(null, keysWithPubKey);
keychainStub.refreshKeyForUserId.withArgs({
userId: emailAddress,
overridePermission: true
}).yields();
emailDaoStub.init.withArgs({
account: {
realname: undefined,
emailAddress: emailAddress,
asymKeySize: config.asymKeySize
}
}).yields();
controller.init({ controller.init({
emailAddress: emailAddress emailAddress: emailAddress
}, function(err, keypair) { }, function(err, keypair) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(keypair).to.exist; expect(keypair.publicKey).to.not.exist;
expect(updateHandlerStub.update.calledOnce).to.be.true; expect(updateHandlerStub.update.calledOnce).to.be.true;
expect(emailDaoStub.init.calledOnce).to.be.true;
expect(devicestorageStub.init.calledOnce).to.be.true; expect(devicestorageStub.init.calledOnce).to.be.true;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
expect(keychainStub.refreshKeyForUserId.calledOnce).to.be.true;
expect(emailDaoStub.init.calledOnce).to.be.true;
done(); done();
}); });
}); });

View File

@ -148,36 +148,18 @@ describe('Email DAO unit tests', function() {
initFoldersStub = sinon.stub(dao, '_initFoldersFromDisk'); initFoldersStub = sinon.stub(dao, '_initFoldersFromDisk');
}); });
it('should initialize folders and return keypair', function(done) { it('should initialize folders', function(done) {
keychainStub.getUserKeyPair.withArgs(emailAddress).yieldsAsync(null, mockKeyPair);
initFoldersStub.yieldsAsync(); initFoldersStub.yieldsAsync();
dao.init({ dao.init({
account: account account: account
}, function(err, keypair) { }, function(err) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(keypair).to.exist;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
expect(initFoldersStub.calledOnce).to.be.true; expect(initFoldersStub.calledOnce).to.be.true;
done(); done();
}); });
}); });
it('should fail when keychain errors', function(done) {
keychainStub.getUserKeyPair.yieldsAsync({});
dao.init({
account: account
}, function(err, keypair) {
expect(err).to.exist;
expect(keypair).to.not.exist;
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
expect(initFoldersStub.called).to.be.false;
done();
});
});
}); });
describe('#unlock', function() { describe('#unlock', function() {

View File

@ -85,7 +85,9 @@ describe('Keychain DAO unit tests', function() {
it('should not find a key', function(done) { it('should not find a key', function(done) {
getPubKeyStub.yields(); getPubKeyStub.yields();
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.not.exist; expect(key).to.not.exist;
@ -97,7 +99,9 @@ describe('Keychain DAO unit tests', function() {
getPubKeyStub.yields(null, oldKey); getPubKeyStub.yields(null, oldKey);
pubkeyDaoStub.get.withArgs(oldKey._id).yields(null, oldKey); pubkeyDaoStub.get.withArgs(oldKey._id).yields(null, oldKey);
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.to.equal(oldKey); expect(key).to.to.equal(oldKey);
@ -121,7 +125,33 @@ describe('Keychain DAO unit tests', function() {
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields(); lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields();
lawnchairDaoStub.persist.withArgs('publickey_' + newKey._id, newKey).yields(); lawnchairDaoStub.persist.withArgs('publickey_' + newKey._id, newKey).yields();
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist;
expect(key).to.equal(newKey);
expect(getPubKeyStub.calledOnce).to.be.true;
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
expect(lawnchairDaoStub.remove.calledOnce).to.be.true;
expect(lawnchairDaoStub.persist.calledOnce).to.be.true;
done();
});
});
it('should update key without approval', function(done) {
getPubKeyStub.yields(null, oldKey);
pubkeyDaoStub.get.withArgs(oldKey._id).yields();
pubkeyDaoStub.getByUserId.withArgs(testUser).yields(null, newKey);
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields();
lawnchairDaoStub.persist.withArgs('publickey_' + newKey._id, newKey).yields();
keychainDao.refreshKeyForUserId({
userId: testUser,
overridePermission: true
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.equal(newKey); expect(key).to.equal(newKey);
@ -146,7 +176,9 @@ describe('Keychain DAO unit tests', function() {
}; };
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields(); lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields();
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.not.exist; expect(key).to.not.exist;
@ -167,7 +199,9 @@ describe('Keychain DAO unit tests', function() {
code: 42 code: 42
}); });
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.to.equal(oldKey); expect(key).to.to.equal(oldKey);
@ -191,7 +225,9 @@ describe('Keychain DAO unit tests', function() {
cb(false); cb(false);
}; };
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.equal(oldKey); expect(key).to.equal(oldKey);
@ -208,7 +244,9 @@ describe('Keychain DAO unit tests', function() {
it('should not remove manually imported key', function(done) { it('should not remove manually imported key', function(done) {
getPubKeyStub.yields(null, importedKey); getPubKeyStub.yields(null, importedKey);
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.equal(importedKey); expect(key).to.equal(importedKey);
@ -225,7 +263,9 @@ describe('Keychain DAO unit tests', function() {
code: 42 code: 42
}); });
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(key).to.to.equal(oldKey); expect(key).to.to.equal(oldKey);
@ -251,7 +291,9 @@ describe('Keychain DAO unit tests', function() {
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields(); lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields();
lawnchairDaoStub.persist.yields({}); lawnchairDaoStub.persist.yields({});
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.exist; expect(err).to.exist;
expect(key).to.not.exist; expect(key).to.not.exist;
@ -275,7 +317,9 @@ describe('Keychain DAO unit tests', function() {
}; };
lawnchairDaoStub.remove.yields({}); lawnchairDaoStub.remove.yields({});
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.exist; expect(err).to.exist;
expect(key).to.not.exist; expect(key).to.not.exist;
@ -301,7 +345,9 @@ describe('Keychain DAO unit tests', function() {
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields(); lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).yields();
lawnchairDaoStub.persist.yields({}); lawnchairDaoStub.persist.yields({});
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.exist; expect(err).to.exist;
expect(key).to.not.exist; expect(key).to.not.exist;
@ -319,7 +365,9 @@ describe('Keychain DAO unit tests', function() {
getPubKeyStub.yields(null, oldKey); getPubKeyStub.yields(null, oldKey);
pubkeyDaoStub.get.withArgs(oldKey._id).yields({}); pubkeyDaoStub.get.withArgs(oldKey._id).yields({});
keychainDao.refreshKeyForUserId(testUser, function(err, key) { keychainDao.refreshKeyForUserId({
userId: testUser
}, function(err, key) {
expect(err).to.exist; expect(err).to.exist;
expect(key).to.not.exist; expect(key).to.not.exist;

View File

@ -364,7 +364,9 @@ describe('Mail List controller unit test', function() {
} }
}; };
keychainMock.refreshKeyForUserId.withArgs(mail.from[0].address).yields(); keychainMock.refreshKeyForUserId.withArgs({
userId: mail.from[0].address
}).yields();
scope.select(mail); scope.select(mail);
@ -397,7 +399,7 @@ describe('Mail List controller unit test', function() {
} }
}; };
keychainMock.refreshKeyForUserId.withArgs(mail.from[0].address).yields(); keychainMock.refreshKeyForUserId.withArgs({userId: mail.from[0].address}).yields();
scope.select(mail); scope.select(mail);

View File

@ -192,7 +192,9 @@ describe('Write controller unit test', function() {
address: 'asds@example.com' address: 'asds@example.com'
}; };
keychainMock.refreshKeyForUserId.withArgs(recipient.address).yields({ keychainMock.refreshKeyForUserId.withArgs({
userId: recipient.address
}).yields({
errMsg: '404 not found yadda yadda' errMsg: '404 not found yadda yadda'
}); });
@ -212,7 +214,9 @@ describe('Write controller unit test', function() {
address: 'asdf@example.com' address: 'asdf@example.com'
}; };
keychainMock.refreshKeyForUserId.withArgs(recipient.address).yields(null, { keychainMock.refreshKeyForUserId.withArgs({
userId: recipient.address
}).yields(null, {
userId: 'asdf@example.com' userId: 'asdf@example.com'
}); });
@ -240,7 +244,9 @@ describe('Write controller unit test', function() {
}] }]
}; };
keychainMock.refreshKeyForUserId.withArgs(recipient.address).yields(null, key); keychainMock.refreshKeyForUserId.withArgs({
userId: recipient.address
}).yields(null, key);
scope.$digest = function() { scope.$digest = function() {
expect(recipient.key).to.deep.equal(key); expect(recipient.key).to.deep.equal(key);