mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 19:02:20 -05:00
Merge branch 'login' into outbox
Conflicts: src/js/app.js
This commit is contained in:
commit
2976e128ed
@ -41,7 +41,7 @@ define(function(require) {
|
||||
/**
|
||||
* Request an OAuth token from chrome for gmail users
|
||||
*/
|
||||
self.fetchOAuthToken = function(passphrase, callback) {
|
||||
self.fetchOAuthToken = function(callback) {
|
||||
// get OAuth Token from chrome
|
||||
chrome.identity.getAuthToken({
|
||||
'interactive': true
|
||||
@ -65,7 +65,10 @@ define(function(require) {
|
||||
}
|
||||
|
||||
// init the email dao
|
||||
self.init(emailAddress, passphrase, token, callback);
|
||||
callback(null, {
|
||||
emailAddress: emailAddress,
|
||||
token: token
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -124,7 +127,7 @@ define(function(require) {
|
||||
/**
|
||||
* Instanciate the mail email data access object and its dependencies. Login to imap on init.
|
||||
*/
|
||||
self.init = function(userId, passphrase, token, callback) {
|
||||
self.init = function(userId, token, callback) {
|
||||
var auth, imapOptions, smtpOptions,
|
||||
keychain, imapClient, smtpClient, pgp, userStorage;
|
||||
|
||||
@ -162,7 +165,7 @@ define(function(require) {
|
||||
emailAddress: userId,
|
||||
asymKeySize: config.asymKeySize
|
||||
};
|
||||
self._emailDao.init(account, passphrase, callback);
|
||||
self._emailDao.init(account, callback);
|
||||
};
|
||||
|
||||
return self;
|
||||
|
@ -4,13 +4,16 @@ window.name = 'NG_DEFER_BOOTSTRAP!';
|
||||
require([
|
||||
'angular',
|
||||
'js/controller/login',
|
||||
'js/controller/login-initial',
|
||||
'js/controller/login-new-device',
|
||||
'js/controller/login-existing',
|
||||
'js/controller/mail-list',
|
||||
'js/controller/read',
|
||||
'js/controller/write',
|
||||
'js/controller/navigation',
|
||||
'angularRoute',
|
||||
'angularTouch'
|
||||
], function(angular, LoginCtrl, MailListCtrl, ReadCtrl, WriteCtrl, NavigationCtrl) {
|
||||
], function(angular, LoginCtrl, LoginInitialCtrl, LoginNewDeviceCtrl, LoginExistingCtrl, MailListCtrl, ReadCtrl, WriteCtrl, NavigationCtrl) {
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('mail', ['ngRoute', 'ngTouch', 'navigation', 'mail-list', 'write', 'read']);
|
||||
@ -18,9 +21,21 @@ require([
|
||||
// set router paths
|
||||
app.config(function($routeProvider) {
|
||||
$routeProvider.when('/login', {
|
||||
templateUrl: 'tpl/login.html',
|
||||
templateUrl: 'tpl/loading.html',
|
||||
controller: LoginCtrl
|
||||
});
|
||||
$routeProvider.when('/login-existing', {
|
||||
templateUrl: 'tpl/login-existing.html',
|
||||
controller: LoginExistingCtrl
|
||||
});
|
||||
$routeProvider.when('/login-initial', {
|
||||
templateUrl: 'tpl/login-initial.html',
|
||||
controller: LoginInitialCtrl
|
||||
});
|
||||
$routeProvider.when('/login-new-device', {
|
||||
templateUrl: 'tpl/login-new-device.html',
|
||||
controller: LoginNewDeviceCtrl
|
||||
});
|
||||
$routeProvider.when('/desktop', {
|
||||
templateUrl: 'tpl/desktop.html',
|
||||
controller: NavigationCtrl
|
||||
|
53
src/js/controller/login-existing.js
Normal file
53
src/js/controller/login-existing.js
Normal file
@ -0,0 +1,53 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginExistingCtrl = function($scope, $location) {
|
||||
|
||||
$scope.confirmPassphrase = function() {
|
||||
var passphrase = $scope.passphrase,
|
||||
emailDao = appController._emailDao;
|
||||
|
||||
if (!passphrase) {
|
||||
return;
|
||||
}
|
||||
|
||||
unlockCrypto(imapLogin);
|
||||
|
||||
function unlockCrypto(callback) {
|
||||
var userId = emailDao._account.emailAddress;
|
||||
emailDao._keychain.getUserKeyPair(userId, function(err, keypair) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
emailDao.unlock(keypair, passphrase, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function imapLogin(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// login to imap backend
|
||||
appController._emailDao.imapLogin(function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
onLogin();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function onLogin() {
|
||||
$location.path('/desktop');
|
||||
$scope.$apply();
|
||||
}
|
||||
};
|
||||
|
||||
return LoginExistingCtrl;
|
||||
});
|
47
src/js/controller/login-initial.js
Normal file
47
src/js/controller/login-initial.js
Normal file
@ -0,0 +1,47 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginInitialCtrl = function($scope, $location) {
|
||||
|
||||
$scope.confirmPassphrase = function() {
|
||||
var passphrase = $scope.passphrase,
|
||||
confirmation = $scope.confirmation,
|
||||
emailDao = appController._emailDao;
|
||||
|
||||
if (!passphrase || passphrase !== confirmation) {
|
||||
return;
|
||||
}
|
||||
|
||||
unlockCrypto(imapLogin);
|
||||
|
||||
function unlockCrypto(callback) {
|
||||
emailDao.unlock({}, passphrase, callback);
|
||||
}
|
||||
|
||||
function imapLogin(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// login to imap backend
|
||||
appController._emailDao.imapLogin(function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
onLogin();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function onLogin() {
|
||||
$location.path('/desktop');
|
||||
$scope.$apply();
|
||||
}
|
||||
};
|
||||
|
||||
return LoginInitialCtrl;
|
||||
});
|
13
src/js/controller/login-new-device.js
Normal file
13
src/js/controller/login-new-device.js
Normal file
@ -0,0 +1,13 @@
|
||||
define(function() {
|
||||
'use strict';
|
||||
|
||||
var LoginExistingCtrl = function($scope) {
|
||||
|
||||
$scope.confirmPassphrase = function() {
|
||||
window.alert('Not implemented yet!');
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
return LoginExistingCtrl;
|
||||
});
|
@ -4,44 +4,52 @@ define(function(require) {
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginCtrl = function($scope, $location) {
|
||||
|
||||
// start the main app controller
|
||||
appController.start(function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.chrome && chrome.identity) {
|
||||
login('passphrase', onLogin);
|
||||
if (!window.chrome || !chrome.identity) {
|
||||
$location.path('/desktop');
|
||||
$scope.$apply();
|
||||
return;
|
||||
}
|
||||
|
||||
onLogin();
|
||||
initializeUser();
|
||||
});
|
||||
|
||||
function login(password, callback) {
|
||||
function initializeUser() {
|
||||
// get OAuth token from chrome
|
||||
appController.fetchOAuthToken(password, function(err) {
|
||||
appController.fetchOAuthToken(function(err, auth) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// login to imap backend
|
||||
appController._emailDao.imapLogin(function(err) {
|
||||
appController.init(auth.emailAddress, auth.token, function(err, availableKeys) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback();
|
||||
redirect(availableKeys);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onLogin() {
|
||||
$location.path('/desktop');
|
||||
function redirect(availableKeys) {
|
||||
// redirect if needed
|
||||
if (!availableKeys.publicKey) {
|
||||
// no public key available, start onboarding process
|
||||
$location.path('/login-initial');
|
||||
} else if (!availableKeys.privateKey) {
|
||||
// no private key, import key
|
||||
$location.path('/login-new-device');
|
||||
} else {
|
||||
// public and private key available, just login
|
||||
$location.path('/login-existing');
|
||||
}
|
||||
$scope.$apply();
|
||||
}
|
||||
};
|
||||
|
@ -22,7 +22,7 @@ define(function(require) {
|
||||
/**
|
||||
* Inits all dependencies
|
||||
*/
|
||||
EmailDAO.prototype.init = function(account, passphrase, callback) {
|
||||
EmailDAO.prototype.init = function(account, callback) {
|
||||
var self = this;
|
||||
|
||||
self._account = account;
|
||||
@ -48,62 +48,63 @@ define(function(require) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
// init crypto
|
||||
initCrypto(storedKeypair);
|
||||
callback(null, storedKeypair);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function initCrypto(storedKeypair) {
|
||||
if (storedKeypair && storedKeypair.privateKey && storedKeypair.publicKey) {
|
||||
// import existing key pair into crypto module
|
||||
self._crypto.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: storedKeypair.privateKey.encryptedKey,
|
||||
publicKeyArmored: storedKeypair.publicKey.publicKey
|
||||
}, callback);
|
||||
EmailDAO.prototype.unlock = function(keypair, passphrase, callback) {
|
||||
var self = this;
|
||||
|
||||
if (keypair && keypair.privateKey && keypair.publicKey) {
|
||||
// import existing key pair into crypto module
|
||||
self._crypto.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: keypair.privateKey.encryptedKey,
|
||||
publicKeyArmored: keypair.publicKey.publicKey
|
||||
}, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// no keypair for is stored for the user... generate a new one
|
||||
self._crypto.generateKeys({
|
||||
emailAddress: self._account.emailAddress,
|
||||
keySize: self._account.asymKeySize,
|
||||
passphrase: passphrase
|
||||
}, function(err, generatedKeypair) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// no keypair for is stored for the user... generate a new one
|
||||
self._crypto.generateKeys({
|
||||
emailAddress: self._account.emailAddress,
|
||||
keySize: self._account.asymKeySize,
|
||||
passphrase: passphrase
|
||||
}, function(err, generatedKeypair) {
|
||||
// import the new key pair into crypto module
|
||||
self._crypto.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: generatedKeypair.privateKeyArmored,
|
||||
publicKeyArmored: generatedKeypair.publicKeyArmored
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// import the new key pair into crypto module
|
||||
self._crypto.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: generatedKeypair.privateKeyArmored,
|
||||
publicKeyArmored: generatedKeypair.publicKeyArmored
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
// persist newly generated keypair
|
||||
var newKeypair = {
|
||||
publicKey: {
|
||||
_id: generatedKeypair.keyId,
|
||||
userId: self._account.emailAddress,
|
||||
publicKey: generatedKeypair.publicKeyArmored
|
||||
},
|
||||
privateKey: {
|
||||
_id: generatedKeypair.keyId,
|
||||
userId: self._account.emailAddress,
|
||||
encryptedKey: generatedKeypair.privateKeyArmored
|
||||
}
|
||||
|
||||
// persist newly generated keypair
|
||||
var newKeypair = {
|
||||
publicKey: {
|
||||
_id: generatedKeypair.keyId,
|
||||
userId: self._account.emailAddress,
|
||||
publicKey: generatedKeypair.publicKeyArmored
|
||||
},
|
||||
privateKey: {
|
||||
_id: generatedKeypair.keyId,
|
||||
userId: self._account.emailAddress,
|
||||
encryptedKey: generatedKeypair.privateKeyArmored
|
||||
}
|
||||
};
|
||||
self._keychain.putUserKeyPair(newKeypair, callback);
|
||||
});
|
||||
};
|
||||
self._keychain.putUserKeyPair(newKeypair, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -155,24 +155,22 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
|
||||
|
||||
// persist private key in local storage
|
||||
self.lookupPrivateKey(keypairId, function(err, savedPrivkey) {
|
||||
var keys = {};
|
||||
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// validate fetched key
|
||||
if (savedPubkey && savedPubkey.publicKey && savedPrivkey && savedPrivkey.encryptedKey) {
|
||||
callback(null, {
|
||||
publicKey: savedPubkey,
|
||||
privateKey: savedPrivkey
|
||||
});
|
||||
return;
|
||||
|
||||
} else {
|
||||
// continue without keypair... generate in crypto.js
|
||||
callback();
|
||||
return;
|
||||
if (savedPubkey && savedPubkey.publicKey) {
|
||||
keys.publicKey = savedPubkey;
|
||||
}
|
||||
|
||||
if (savedPrivkey && savedPrivkey.encryptedKey) {
|
||||
keys.privateKey = savedPrivkey;
|
||||
}
|
||||
|
||||
callback(null, keys);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -250,33 +248,9 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
|
||||
};
|
||||
|
||||
KeychainDAO.prototype.lookupPrivateKey = function(id, callback) {
|
||||
var self = this;
|
||||
|
||||
// lookup in local storage
|
||||
jsonDao.read('privatekey_' + id, function(privkey) {
|
||||
if (!privkey) {
|
||||
// fetch from cloud storage
|
||||
self._cloudstorage.getPrivateKey(id, function(err, cloudPrivkey) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache private key in cache
|
||||
self.saveLocalPrivateKey(cloudPrivkey, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, cloudPrivkey);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
callback(null, privkey);
|
||||
}
|
||||
callback(null, privkey);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -23,3 +23,4 @@
|
||||
@import "views/mail-list";
|
||||
@import "views/read";
|
||||
@import "views/write";
|
||||
@import "views/login";
|
||||
|
49
src/sass/views/_login.scss
Normal file
49
src/sass/views/_login.scss
Normal file
@ -0,0 +1,49 @@
|
||||
.view-login {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #F9F9F9;
|
||||
|
||||
h1, a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 -1px 1px $color-grey-medium;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 0 $nav-padding;
|
||||
height: 84px;
|
||||
h1 {
|
||||
font-family: 'Mensch';
|
||||
font-weight: normal;
|
||||
font-size: 5em;
|
||||
height: 100px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
padding-top: 10px;
|
||||
color: #00C6FF;
|
||||
|
||||
span {
|
||||
font-family: 'Mensch Thin';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 100px $nav-padding 0 $nav-padding;
|
||||
|
||||
input {
|
||||
border: 0!important;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.passphrase {}
|
||||
|
||||
.confirm-control {}
|
||||
|
||||
.info-text {
|
||||
text-align:justify;
|
||||
text-justify:inter-word;
|
||||
}
|
||||
}
|
||||
}
|
1
src/tpl/loading.html
Normal file
1
src/tpl/loading.html
Normal file
@ -0,0 +1 @@
|
||||
<p>loading...</p>
|
15
src/tpl/login-existing.html
Normal file
15
src/tpl/login-existing.html
Normal file
@ -0,0 +1,15 @@
|
||||
<div class="view-login">
|
||||
<header>
|
||||
<h1>WHITEOUT<span>.IO</span></h1>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="passphrase">
|
||||
<p><span>Please enter your passphrase: </span><input type="password" ng-model="passphrase" class="passphrase" placeholder="Passphrase" tabindex="1"></p>
|
||||
</div>
|
||||
|
||||
<div class="confirm-control">
|
||||
<button ng-click="confirmPassphrase()" class="btn" ng-disabled="!passphrase" tabindex="2">Confirm passphrase</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
src/tpl/login-initial.html
Normal file
23
src/tpl/login-initial.html
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="view-login">
|
||||
<header>
|
||||
<h1>WHITEOUT<span>.IO</span></h1>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="passphrase">
|
||||
<p><span>Please enter your passphrase: </span><input type="password" ng-model="passphrase" class="passphrase" placeholder="Passphrase" tabindex="1"></p>
|
||||
</div>
|
||||
|
||||
<div class="info-text">
|
||||
<p>Your passphrase protects the secrets that protect your privacy. You are the only person in charge of your privacy, which is a good thing and the way it should be. The passphrase will <b>never</b> be stored by this application. So you might want to write it down and put it into a <b>safe</b> place. You will need this passphrase when you re-open this application. If you lose the passphrase, your communication is irretrievably lost and <b>cannot be restored</b>.</p>
|
||||
</div>
|
||||
|
||||
<div class="passphrase">
|
||||
<p><span>Please confirm your passphrase: </span><input type="password" ng-model="confirmation" class="confirmation" placeholder="Confirmation" tabindex="2"></p>
|
||||
</div>
|
||||
|
||||
<div class="confirm-control">
|
||||
<button ng-click="confirmPassphrase()" class="btn" ng-disabled="!passphrase || passphrase!==confirmation" tabindex="3">Confirm passphrase</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
1
src/tpl/login-new-device.html
Normal file
1
src/tpl/login-new-device.html
Normal file
@ -0,0 +1 @@
|
||||
<p>not implemented yet...</p>
|
@ -1 +0,0 @@
|
||||
<div class="message">Logging in...</div>
|
@ -59,7 +59,7 @@ define(function(require) {
|
||||
controller._appConfigStore.listItems.yields(null, []);
|
||||
controller._appConfigStore.storeList.yields();
|
||||
|
||||
controller.fetchOAuthToken(appControllerTest.passphrase, function(err) {
|
||||
controller.fetchOAuthToken(function(err) {
|
||||
expect(err).to.not.exist;
|
||||
expect(controller._appConfigStore.listItems.calledOnce).to.be.true;
|
||||
expect(controller._appConfigStore.storeList.calledOnce).to.be.true;
|
||||
@ -72,7 +72,7 @@ define(function(require) {
|
||||
it('should work when the email address is cached', function(done) {
|
||||
controller._appConfigStore.listItems.yields(null, ['asdf']);
|
||||
|
||||
controller.fetchOAuthToken(appControllerTest.passphrase, function(err) {
|
||||
controller.fetchOAuthToken(function(err) {
|
||||
expect(err).to.not.exist;
|
||||
expect(controller._appConfigStore.listItems.calledOnce).to.be.true;
|
||||
expect(window.chrome.identity.getAuthToken.calledOnce).to.be.true;
|
||||
|
@ -53,61 +53,129 @@ define(function(require) {
|
||||
devicestorageStub = sinon.createStubInstance(DeviceStorageDAO);
|
||||
|
||||
emailDao = new EmailDAO(keychainStub, imapClientStub, smtpClientStub, pgpStub, devicestorageStub);
|
||||
emailDao._account = account;
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
describe('init', function() {
|
||||
beforeEach(function() {
|
||||
delete emailDao._account;
|
||||
});
|
||||
|
||||
it('should fail due to error in getUserKeyPair', function(done) {
|
||||
devicestorageStub.init.yields();
|
||||
keychainStub.getUserKeyPair.yields(42);
|
||||
|
||||
emailDao.init(account, emaildaoTest.passphrase, function(err) {
|
||||
emailDao.init(account, function(err) {
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(err).to.equal(42);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should init with new keygen', function(done) {
|
||||
it('should init', function(done) {
|
||||
var mockKeyPair = {};
|
||||
|
||||
devicestorageStub.init.yields();
|
||||
keychainStub.getUserKeyPair.yields();
|
||||
keychainStub.getUserKeyPair.yields(null, mockKeyPair);
|
||||
|
||||
emailDao.init(account, function(err, keyPair) {
|
||||
expect(err).to.not.exist;
|
||||
|
||||
expect(keyPair === mockKeyPair).to.be.true;
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('unlock', function() {
|
||||
it('should unlock with new key', function(done) {
|
||||
pgpStub.generateKeys.yields(null, {});
|
||||
pgpStub.importKeys.yields();
|
||||
keychainStub.putUserKeyPair.yields();
|
||||
|
||||
emailDao.init(account, emaildaoTest.passphrase, function(err) {
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
|
||||
emailDao.unlock({}, emaildaoTest.passphrase, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
expect(keychainStub.putUserKeyPair.calledOnce).to.be.true;
|
||||
expect(err).to.not.exist;
|
||||
expect(pgpStub.generateKeys.calledWith({
|
||||
emailAddress: account.emailAddress,
|
||||
keySize: account.asymKeySize,
|
||||
passphrase: emaildaoTest.passphrase
|
||||
})).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should init with stored keygen', function(done) {
|
||||
devicestorageStub.init.yields();
|
||||
keychainStub.getUserKeyPair.yields(null, {
|
||||
publicKey: {
|
||||
_id: 'keyId',
|
||||
userId: emaildaoTest.user,
|
||||
publicKey: 'publicKeyArmored'
|
||||
},
|
||||
privateKey: {
|
||||
_id: 'keyId',
|
||||
userId: emaildaoTest.user,
|
||||
encryptedKey: 'privateKeyArmored'
|
||||
}
|
||||
});
|
||||
it('should unlock with existing key pair', function(done) {
|
||||
pgpStub.importKeys.yields();
|
||||
|
||||
emailDao.init(account, emaildaoTest.passphrase, function(err) {
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
emailDao.unlock({
|
||||
privateKey: {
|
||||
encryptedKey: 'cryptocrypto'
|
||||
},
|
||||
publicKey: {
|
||||
publicKey: 'omgsocrypto'
|
||||
}
|
||||
}, emaildaoTest.passphrase, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledWith({
|
||||
passphrase: emaildaoTest.passphrase,
|
||||
privateKeyArmored: 'cryptocrypto',
|
||||
publicKeyArmored: 'omgsocrypto'
|
||||
})).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not unlock with error during keygen', function(done) {
|
||||
pgpStub.generateKeys.yields(new Error('fubar'));
|
||||
|
||||
emailDao.unlock({}, emaildaoTest.passphrase, function(err) {
|
||||
expect(err).to.exist;
|
||||
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not unloch with error during key import', function(done) {
|
||||
pgpStub.generateKeys.yields(null, {});
|
||||
pgpStub.importKeys.yields(new Error('fubar'));
|
||||
|
||||
emailDao.unlock({}, emaildaoTest.passphrase, function(err) {
|
||||
expect(err).to.exist;
|
||||
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not unlock with error during key store', function(done) {
|
||||
pgpStub.generateKeys.yields(null, {});
|
||||
pgpStub.importKeys.yields();
|
||||
keychainStub.putUserKeyPair.yields(new Error('omgwtf'));
|
||||
|
||||
emailDao.unlock({}, emaildaoTest.passphrase, function(err) {
|
||||
expect(err).to.exist;
|
||||
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
expect(keychainStub.putUserKeyPair.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -141,14 +209,16 @@ define(function(require) {
|
||||
pgpStub.importKeys.yields();
|
||||
keychainStub.putUserKeyPair.yields();
|
||||
|
||||
emailDao.init(account, emaildaoTest.passphrase, function(err) {
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
expect(keychainStub.putUserKeyPair.calledOnce).to.be.true;
|
||||
expect(err).to.not.exist;
|
||||
done();
|
||||
emailDao.init(account, function(err, keyPair) {
|
||||
emailDao.unlock(keyPair, emaildaoTest.passphrase, function(err) {
|
||||
expect(devicestorageStub.init.calledOnce).to.be.true;
|
||||
expect(keychainStub.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(pgpStub.generateKeys.calledOnce).to.be.true;
|
||||
expect(pgpStub.importKeys.calledOnce).to.be.true;
|
||||
expect(keychainStub.putUserKeyPair.calledOnce).to.be.true;
|
||||
expect(err).to.not.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user