mirror of
https://github.com/moparisthebest/mail
synced 2024-12-22 23:38:48 -05:00
Merge pull request #35 from whiteout-io/dev/import-pubkey
Dev/import pubkey
This commit is contained in:
commit
45e6b7834a
@ -7,6 +7,7 @@ requirejs([
|
||||
'js/controller/popover',
|
||||
'js/controller/add-account',
|
||||
'js/controller/account',
|
||||
'js/controller/contacts',
|
||||
'js/controller/login',
|
||||
'js/controller/login-initial',
|
||||
'js/controller/login-new-device',
|
||||
@ -24,6 +25,7 @@ requirejs([
|
||||
PopoverCtrl,
|
||||
AddAccountCtrl,
|
||||
AccountCtrl,
|
||||
ContactsCtrl,
|
||||
LoginCtrl,
|
||||
LoginInitialCtrl,
|
||||
LoginNewDeviceCtrl,
|
||||
@ -32,14 +34,25 @@ requirejs([
|
||||
ReadCtrl,
|
||||
WriteCtrl,
|
||||
NavigationCtrl,
|
||||
util) {
|
||||
util
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
// reset window.name
|
||||
window.name = util.UUID();
|
||||
|
||||
// init main angular module including dependencies
|
||||
var app = angular.module('mail', ['ngRoute', 'ngTouch', 'navigation', 'mail-list', 'write', 'read', 'login-new-device', 'popover']);
|
||||
var app = angular.module('mail', [
|
||||
'ngRoute',
|
||||
'ngTouch',
|
||||
'navigation',
|
||||
'mail-list',
|
||||
'write',
|
||||
'read',
|
||||
'contacts',
|
||||
'login-new-device',
|
||||
'popover'
|
||||
]);
|
||||
|
||||
// set router paths
|
||||
app.config(function($routeProvider) {
|
||||
@ -77,6 +90,7 @@ requirejs([
|
||||
app.controller('WriteCtrl', WriteCtrl);
|
||||
app.controller('MailListCtrl', MailListCtrl);
|
||||
app.controller('AccountCtrl', AccountCtrl);
|
||||
app.controller('ContactsCtrl', ContactsCtrl);
|
||||
app.controller('DialogCtrl', DialogCtrl);
|
||||
app.controller('PopoverCtrl', PopoverCtrl);
|
||||
|
||||
|
140
src/js/controller/contacts.js
Normal file
140
src/js/controller/contacts.js
Normal file
@ -0,0 +1,140 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular'),
|
||||
_ = require('underscore'),
|
||||
appController = require('js/app-controller'),
|
||||
keychain, pgp;
|
||||
|
||||
//
|
||||
// Controller
|
||||
//
|
||||
|
||||
var ContactsCtrl = function($scope) {
|
||||
keychain = appController._keychain,
|
||||
pgp = appController._crypto;
|
||||
|
||||
$scope.state.contacts = {
|
||||
open: false,
|
||||
toggle: function(to) {
|
||||
this.open = to;
|
||||
$scope.listKeys();
|
||||
}
|
||||
};
|
||||
|
||||
// set default value so that the popover height is correct on init
|
||||
$scope.fingerprint = 'XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX';
|
||||
|
||||
//
|
||||
// scope functions
|
||||
//
|
||||
|
||||
$scope.listKeys = function() {
|
||||
keychain.listLocalPublicKeys(function(err, keys) {
|
||||
if (err) {
|
||||
$scope.onError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
keys.forEach(addParams);
|
||||
|
||||
$scope.keys = keys;
|
||||
$scope.$apply();
|
||||
|
||||
function addParams(key) {
|
||||
var params = pgp.getKeyParams(key.publicKey);
|
||||
_.extend(key, params);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getFingerprint = function(key) {
|
||||
var fpr = key.fingerprint;
|
||||
var formatted = fpr.slice(0, 4) + ' ' + fpr.slice(4, 8) + ' ' + fpr.slice(8, 12) + ' ' + fpr.slice(12, 16) + ' ' + fpr.slice(16, 20) + ' ... ' + fpr.slice(20, 24) + ' ' + fpr.slice(24, 28) + ' ' + fpr.slice(28, 32) + ' ' + fpr.slice(32, 36) + ' ' + fpr.slice(36);
|
||||
|
||||
$scope.fingerprint = formatted;
|
||||
};
|
||||
|
||||
$scope.importKey = function(publicKeyArmored) {
|
||||
var keyParams, pubkey;
|
||||
|
||||
// verifiy public key string
|
||||
if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
|
||||
$scope.onError({
|
||||
errMsg: 'Invalid public key!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
keyParams = pgp.getKeyParams(publicKeyArmored);
|
||||
} catch (e) {
|
||||
$scope.onError(e);
|
||||
return;
|
||||
}
|
||||
|
||||
pubkey = {
|
||||
_id: keyParams._id,
|
||||
userId: keyParams.userId,
|
||||
publicKey: publicKeyArmored
|
||||
};
|
||||
|
||||
keychain.saveLocalPublicKey(pubkey, function(err) {
|
||||
if (err) {
|
||||
$scope.onError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// update displayed keys
|
||||
$scope.listKeys();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.removeKey = function(key) {
|
||||
keychain.removeLocalPublicKey(key._id, function(err) {
|
||||
if (err) {
|
||||
$scope.onError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// update displayed keys
|
||||
$scope.listKeys();
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// Directives
|
||||
//
|
||||
|
||||
var ngModule = angular.module('contacts', []);
|
||||
|
||||
ngModule.directive('keyfileInput', function() {
|
||||
return function(scope, elm) {
|
||||
elm.on('change', function(e) {
|
||||
for (var i = 0; i < e.target.files.length; i++) {
|
||||
importKey(e.target.files.item(i));
|
||||
}
|
||||
});
|
||||
|
||||
function importKey(file) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
scope.importKey(e.target.result);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
ngModule.directive('keyfileBtn', function() {
|
||||
return function(scope, elm) {
|
||||
elm.on('click touchstart', function(e) {
|
||||
e.preventDefault();
|
||||
document.querySelector('#keyfile-input').click();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return ContactsCtrl;
|
||||
});
|
@ -172,6 +172,11 @@ define(function(require) {
|
||||
e.preventDefault();
|
||||
scope.state.account.toggle(false);
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.contacts.open) {
|
||||
// escape -> close contacts view
|
||||
e.preventDefault();
|
||||
scope.state.contacts.toggle(false);
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.nav.open) {
|
||||
// escape -> close nav view
|
||||
e.preventDefault();
|
||||
|
@ -68,13 +68,8 @@ define(function(require) {
|
||||
return fingerprint(this._publicKey);
|
||||
};
|
||||
|
||||
PGP.prototype.getUserId = function(keyArmored) {
|
||||
var key = openpgp.key.readArmored(keyArmored).keys[0];
|
||||
return key.getUserIds()[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a user's key id
|
||||
* Show a user's key id.
|
||||
*/
|
||||
PGP.prototype.getKeyId = function(keyArmored) {
|
||||
var key, pubKeyId, privKeyId;
|
||||
@ -100,6 +95,23 @@ define(function(require) {
|
||||
return pubKeyId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read all relevant params of an armored key.
|
||||
*/
|
||||
PGP.prototype.getKeyParams = function(keyArmored) {
|
||||
var key = openpgp.key.readArmored(keyArmored).keys[0],
|
||||
packet = key.getKeyPacket();
|
||||
|
||||
return {
|
||||
_id: packet.getKeyId().toHex().toUpperCase(),
|
||||
userId: key.getUserIds()[0].split('<')[1].split('>')[0],
|
||||
fingerprint: util.hexstrdump(packet.getFingerprint()).toUpperCase(),
|
||||
algorithm: packet.algorithm,
|
||||
bitSize: packet.getBitSize(),
|
||||
created: packet.created,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Import the user's key pair
|
||||
*/
|
||||
|
@ -156,8 +156,8 @@ define(function(require) {
|
||||
}
|
||||
|
||||
// check if the key's user ID matches the current account
|
||||
pubUserID = self._crypto.getUserId(keypair.publicKey.publicKey);
|
||||
privUserID = self._crypto.getUserId(keypair.privateKey.encryptedKey);
|
||||
pubUserID = self._crypto.getKeyParams(keypair.publicKey.publicKey).userId;
|
||||
privUserID = self._crypto.getKeyParams(keypair.privateKey.encryptedKey).userId;
|
||||
if (pubUserID.indexOf(self._account.emailAddress) === -1 || privUserID.indexOf(self._account.emailAddress) === -1) {
|
||||
callback({
|
||||
errMsg: 'User IDs dont match!'
|
||||
@ -1342,4 +1342,4 @@ define(function(require) {
|
||||
};
|
||||
|
||||
return EmailDAO;
|
||||
});
|
||||
});
|
@ -256,31 +256,43 @@ define(function(require) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pubkey) {
|
||||
// fetch from cloud storage
|
||||
self._publicKeyDao.get(id, function(err, cloudPubkey) {
|
||||
if (pubkey) {
|
||||
callback(null, pubkey);
|
||||
return;
|
||||
}
|
||||
|
||||
// fetch from cloud storage
|
||||
self._publicKeyDao.get(id, function(err, cloudPubkey) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache public key in cache
|
||||
self.saveLocalPublicKey(cloudPubkey, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache public key in cache
|
||||
self.saveLocalPublicKey(cloudPubkey, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, cloudPubkey);
|
||||
});
|
||||
callback(null, cloudPubkey);
|
||||
});
|
||||
|
||||
} else {
|
||||
callback(null, pubkey);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* List all the locally stored public keys
|
||||
*/
|
||||
KeychainDAO.prototype.listLocalPublicKeys = function(callback) {
|
||||
// search local keyring for public key
|
||||
this._localDbDao.list('publickey', 0, null, callback);
|
||||
};
|
||||
|
||||
KeychainDAO.prototype.removeLocalPublicKey = function(id, callback) {
|
||||
this._localDbDao.remove('publickey_' + id, callback);
|
||||
};
|
||||
|
||||
KeychainDAO.prototype.lookupPrivateKey = function(id, callback) {
|
||||
// lookup in local storage
|
||||
this._localDbDao.read('privatekey_' + id, callback);
|
||||
|
@ -24,6 +24,7 @@
|
||||
@import "views/shared";
|
||||
@import "views/add-account";
|
||||
@import "views/account";
|
||||
@import "views/contacts";
|
||||
@import "views/dialog";
|
||||
@import "views/navigation";
|
||||
@import "views/mail-list";
|
||||
|
@ -20,6 +20,7 @@
|
||||
transition: background-color 0.3s;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
outline: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -28,7 +29,6 @@
|
||||
|
||||
&:active,
|
||||
&.active {
|
||||
outline: 0;
|
||||
background-image: none;
|
||||
box-shadow: none;
|
||||
top: 1px;
|
||||
|
42
src/sass/views/_contacts.scss
Normal file
42
src/sass/views/_contacts.scss
Normal file
@ -0,0 +1,42 @@
|
||||
.view-contacts {
|
||||
|
||||
.key-controls {
|
||||
margin: 30px;
|
||||
|
||||
input[type=text] {
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
input[type=file] {
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.key-list {
|
||||
max-height: 400px;
|
||||
margin: 20px;
|
||||
overflow-y: scroll;
|
||||
|
||||
table {
|
||||
th, td {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.remove {
|
||||
font-family: $font-family-icons;
|
||||
font-size: 0.75em;
|
||||
color: $color-grey-input;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -79,6 +79,8 @@
|
||||
margin-top: em(50, 16);
|
||||
padding: 0 $nav-padding;
|
||||
li {
|
||||
margin-bottom: 0.25em;
|
||||
|
||||
a {
|
||||
font-size: $font-size-big;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
<div class="content">
|
||||
<div class="view-account">
|
||||
<table summary="Kontakt">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Email</td>
|
||||
|
45
src/tpl/contacts.html
Normal file
45
src/tpl/contacts.html
Normal file
@ -0,0 +1,45 @@
|
||||
<div class="lightbox-body" ng-controller="ContactsCtrl">
|
||||
<header>
|
||||
<h2>Contacts</h2>
|
||||
<button class="close" ng-click="state.contacts.toggle(false)" data-action="lightbox-close"></button>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="view-contacts">
|
||||
|
||||
<div class="key-controls">
|
||||
<input class="input-text" type="text" placeholder="Search..." ng-model="searchText">
|
||||
<span>
|
||||
<input id="keyfile-input" type="file" multiple accept=".asc" keyfile-input>
|
||||
<button class="btn" ng-class="{'btn-primary': sendBtnSecure === false}" keyfile-btn>Import public keys</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="key-list">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key ID</th>
|
||||
<th>Email</th>
|
||||
<th>Created</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
<tr ng-repeat="key in keys | orderBy:'userId' | filter:searchText">
|
||||
<td class="hover" ng-mouseover="getFingerprint(key)" popover="#fingerprint-contact">{{key._id.slice(8)}}</td>
|
||||
<td>{{key.userId}}</td>
|
||||
<td>{{key.created | date:'mediumDate'}}</td>
|
||||
<td>{{key.bitSize}} bit</td>
|
||||
<td><button class="remove" ng-click="removeKey(key)"></button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div><!-- /.view-contacts -->
|
||||
</div><!-- /.content -->
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="fingerprint-contact" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="popover-title"><b>Fingerprint</b></div>
|
||||
<div class="popover-content">{{fingerprint}}</div>
|
||||
</div><!--/.popover-->
|
||||
|
||||
</div><!-- /.lightbox-body -->
|
@ -25,6 +25,9 @@
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.account.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/account.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.contacts.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/contacts.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div>
|
@ -8,7 +8,7 @@
|
||||
|
||||
<form>
|
||||
<div>
|
||||
<input type="file" file-reader tabindex="1">
|
||||
<input type="file" accept=".asc" file-reader tabindex="1">
|
||||
<span class="popover-info" data-icon-append="" popover="#keyfile-info"></span>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<div class="list-wrapper" ng-iscroll="filteredMessages.length">
|
||||
<ul class="mail-list">
|
||||
<li ng-class="{'mail-list-active': email === state.mailList.selected, 'mail-list-attachment': email.attachments !== undefined && email.attachments.length > 0, 'mail-list-unread': email.unread, 'mail-list-replied': !email.unread && email.answered}" ng-click="select(email)" ng-repeat="email in (filteredMessages = (state.nav.currentFolder.messages | orderBy:'uid':true | filter:searchText))">
|
||||
<li ng-class="{'mail-list-active': email === state.mailList.selected, 'mail-list-attachment': email.attachments !== undefined && email.attachments.length > 0, 'mail-list-unread': email.unread, 'mail-list-replied': !email.unread && email.answered}" ng-click="select(email)" ng-repeat="email in (filteredMessages = (state.nav.currentFolder.messages | filter:searchText | orderBy:'uid':true | limitTo:100))">
|
||||
<h3>{{email.from[0].name || email.from[0].address}}</h3>
|
||||
<div class="encrypted" data-icon="{{email.encrypted ? '' : ''}}"></div>
|
||||
<div class="head">
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
<ul class="nav-secondary">
|
||||
<li><a href="#" ng-click="state.account.toggle(true); $event.preventDefault()">Account</a></li>
|
||||
<li><a href="http://whiteout.io" target="_blank">About whiteout.io</a></li>
|
||||
<li><a href="#" ng-click="state.contacts.toggle(true); $event.preventDefault()">Contacts</a></li>
|
||||
<li><a href="http://whiteout.io" target="_blank">About</a></li>
|
||||
</ul>
|
||||
|
||||
<footer>
|
||||
|
@ -20,10 +20,8 @@ define(function(require) {
|
||||
|
||||
beforeEach(function() {
|
||||
origEmailDao = appController._emailDao;
|
||||
cryptoMock = sinon.createStubInstance(PGP);
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
emailDaoMock._crypto = cryptoMock;
|
||||
appController._emailDao = emailDaoMock;
|
||||
appController._emailDao = emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
emailDaoMock._crypto = cryptoMock = sinon.createStubInstance(PGP);
|
||||
|
||||
dummyFingerprint = '3A2D39B4E1404190B8B949DE7D7E99036E712926';
|
||||
expectedFingerprint = '3A2D 39B4 E140 4190 B8B9 49DE 7D7E 9903 6E71 2926';
|
||||
|
188
test/new-unit/contacts-ctrl-test.js
Normal file
188
test/new-unit/contacts-ctrl-test.js
Normal file
@ -0,0 +1,188 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
ContactsCtrl = require('js/controller/contacts'),
|
||||
appController = require('js/app-controller'),
|
||||
KeychainDAO = require('js/dao/keychain-dao'),
|
||||
PGP = require('js/crypto/pgp');
|
||||
|
||||
describe('Contacts Controller unit test', function() {
|
||||
var scope, contactsCtrl,
|
||||
origKeychain, keychainMock,
|
||||
origCrypto, cryptoMock;
|
||||
|
||||
beforeEach(function() {
|
||||
origCrypto = appController._crypto;
|
||||
appController._crypto = cryptoMock = sinon.createStubInstance(PGP);
|
||||
origKeychain = appController._keychain;
|
||||
appController._keychain = keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||
|
||||
angular.module('contactstest', []);
|
||||
mocks.module('contactstest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
contactsCtrl = $controller(ContactsCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._crypto = origCrypto;
|
||||
appController._keychain = origKeychain;
|
||||
});
|
||||
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.fingerprint).to.equal('XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX');
|
||||
expect(scope.state.contacts.open).to.be.false;
|
||||
expect(scope.state.contacts.toggle).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('listKeys', function() {
|
||||
it('should fail due to error in keychain.listLocalPublicKeys', function(done) {
|
||||
keychainMock.listLocalPublicKeys.yields(42);
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err).to.equal(42);
|
||||
done();
|
||||
};
|
||||
|
||||
scope.listKeys();
|
||||
});
|
||||
|
||||
it('should work', function(done) {
|
||||
keychainMock.listLocalPublicKeys.yields(null, [{
|
||||
_id: '12345'
|
||||
}]);
|
||||
cryptoMock.getKeyParams.returns({
|
||||
fingerprint: 'asdf'
|
||||
});
|
||||
|
||||
scope.$apply = function() {
|
||||
expect(scope.keys.length).to.equal(1);
|
||||
expect(scope.keys[0]._id).to.equal('12345');
|
||||
expect(scope.keys[0].fingerprint).to.equal('asdf');
|
||||
done();
|
||||
};
|
||||
|
||||
expect(scope.keys).to.not.exist;
|
||||
scope.listKeys();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFingerprint', function() {
|
||||
it('should work', function() {
|
||||
var key = {
|
||||
fingerprint: 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
|
||||
};
|
||||
|
||||
scope.getFingerprint(key);
|
||||
|
||||
expect(scope.fingerprint).to.equal('YYYY YYYY YYYY YYYY YYYY ... YYYY YYYY YYYY YYYY YYYY');
|
||||
});
|
||||
});
|
||||
|
||||
describe('importKey', function() {
|
||||
it('should work', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
cryptoMock.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com'
|
||||
});
|
||||
|
||||
keychainMock.saveLocalPublicKey.withArgs({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com',
|
||||
publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----'
|
||||
}).yields();
|
||||
|
||||
scope.listKeys = function() {
|
||||
done();
|
||||
};
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
});
|
||||
|
||||
it('should fail due to invalid armored key', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PRIVATE KEY BLOCK-----';
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err).to.exist;
|
||||
done();
|
||||
};
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
});
|
||||
|
||||
it('should fail due to error in pgp.getKeyParams', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
cryptoMock.getKeyParams.throws(new Error('WAT'));
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err).to.exist;
|
||||
done();
|
||||
};
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
});
|
||||
|
||||
it('should fail due to error in keychain.saveLocalPublicKey', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
cryptoMock.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com'
|
||||
});
|
||||
|
||||
keychainMock.saveLocalPublicKey.yields(42);
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err).to.equal(42);
|
||||
done();
|
||||
};
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeKey', function() {
|
||||
it('should work', function(done) {
|
||||
var key = {
|
||||
_id: '12345'
|
||||
};
|
||||
|
||||
keychainMock.removeLocalPublicKey.withArgs('12345').yields();
|
||||
|
||||
scope.listKeys = function() {
|
||||
done();
|
||||
};
|
||||
|
||||
scope.removeKey(key);
|
||||
});
|
||||
|
||||
it('should fail due to error in keychain.removeLocalPublicKey', function(done) {
|
||||
var key = {
|
||||
_id: '12345'
|
||||
};
|
||||
|
||||
keychainMock.removeLocalPublicKey.withArgs('12345').yields(42);
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err).to.equal(42);
|
||||
done();
|
||||
};
|
||||
|
||||
scope.removeKey(key);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -354,7 +354,9 @@ define(function(require) {
|
||||
_pgpbuilder: {}
|
||||
};
|
||||
|
||||
pgpStub.getUserId.returns('Whiteout User <' + emailAddress + '>');
|
||||
pgpStub.getKeyParams.returns({
|
||||
userId: emailAddress
|
||||
});
|
||||
|
||||
pgpStub.importKeys.withArgs({
|
||||
passphrase: passphrase,
|
||||
|
@ -32,6 +32,30 @@ define(function(require) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('listLocalPublicKeys', function() {
|
||||
it('should work', function(done) {
|
||||
lawnchairDaoStub.list.withArgs('publickey', 0, null).yields();
|
||||
|
||||
keychainDao.listLocalPublicKeys(function() {
|
||||
expect(lawnchairDaoStub.list.callCount).to.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeLocalPublicKey', function() {
|
||||
it('should work', function(done) {
|
||||
var id = 'asdf';
|
||||
|
||||
lawnchairDaoStub.remove.withArgs('publickey_' + id).yields();
|
||||
|
||||
keychainDao.removeLocalPublicKey(id, function() {
|
||||
expect(lawnchairDaoStub.remove.callCount).to.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookup public key', function() {
|
||||
it('should fail', function(done) {
|
||||
keychainDao.lookupPublicKey(undefined, function(err, key) {
|
||||
|
@ -39,6 +39,7 @@ function startTests() {
|
||||
'test/new-unit/dialog-ctrl-test',
|
||||
'test/new-unit/add-account-ctrl-test',
|
||||
'test/new-unit/account-ctrl-test',
|
||||
'test/new-unit/contacts-ctrl-test',
|
||||
'test/new-unit/login-existing-ctrl-test',
|
||||
'test/new-unit/login-initial-ctrl-test',
|
||||
'test/new-unit/login-new-device-ctrl-test',
|
||||
|
@ -5,7 +5,7 @@ define(function(require) {
|
||||
expect = chai.expect;
|
||||
|
||||
describe('PGP Crypto Api unit tests', function() {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
|
||||
var pgp,
|
||||
user = 'whiteout.test@t-online.de',
|
||||
@ -150,13 +150,6 @@ define(function(require) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Get UserId', function() {
|
||||
it('should work with param', function() {
|
||||
var userId = pgp.getUserId(pubkey);
|
||||
expect(userId).to.contain(user);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Get Fingerprint', function() {
|
||||
it('should work without param', function() {
|
||||
var fingerprint = pgp.getFingerprint();
|
||||
@ -169,6 +162,17 @@ define(function(require) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getKeyParams', function() {
|
||||
it('should work with param', function() {
|
||||
var params = pgp.getKeyParams(pubkey);
|
||||
expect(params.fingerprint).to.equal('5856CEF789C3A307E8A1B976F6F60E9B42CDFF4C');
|
||||
expect(params._id).to.equal("F6F60E9B42CDFF4C");
|
||||
expect(params.bitSize).to.equal(keySize);
|
||||
expect(params.userId).to.equal("whiteout.test@t-online.de");
|
||||
expect(params.algorithm).to.equal("rsa_encrypt_sign");
|
||||
});
|
||||
});
|
||||
|
||||
describe('Encrypt and sign', function() {
|
||||
it('should fail', function(done) {
|
||||
var input = null;
|
||||
|
Loading…
Reference in New Issue
Block a user