mirror of
https://github.com/moparisthebest/mail
synced 2025-01-08 12:08:07 -05:00
Implement HKP server support
* Add public key import lightbox for copy and paste * Fix refresh of pgp key change in keychain * Display additional contacts info * Filter by name and email addres in autocomplete * Accept all file endings for key import Accept all types of files for key import
This commit is contained in:
parent
038437595e
commit
c93eaf17f3
@ -189,6 +189,7 @@ module.exports = function(grunt) {
|
||||
'test/unit/controller/login/login-ctrl-test.js',
|
||||
'test/unit/controller/app/dialog-ctrl-test.js',
|
||||
'test/unit/controller/app/privatekey-upload-ctrl-test.js',
|
||||
'test/unit/controller/app/publickey-import-ctrl-test.js',
|
||||
'test/unit/controller/app/account-ctrl-test.js',
|
||||
'test/unit/controller/app/set-passphrase-ctrl-test.js',
|
||||
'test/unit/controller/app/contacts-ctrl-test.js',
|
||||
|
@ -13,6 +13,7 @@ module.exports = appCfg;
|
||||
*/
|
||||
appCfg.config = {
|
||||
cloudUrl: 'https://keys.whiteout.io',
|
||||
hkpUrl: 'https://pgp.mit.edu',
|
||||
privkeyServerUrl: 'https://keychain.whiteout.io',
|
||||
adminUrl: 'https://admin-node.whiteout.io',
|
||||
settingsUrl: 'https://settings.whiteout.io/autodiscovery/',
|
||||
|
@ -111,6 +111,7 @@ app.controller('MailListCtrl', require('./controller/app/mail-list'));
|
||||
app.controller('AccountCtrl', require('./controller/app/account'));
|
||||
app.controller('SetPassphraseCtrl', require('./controller/app/set-passphrase'));
|
||||
app.controller('PrivateKeyUploadCtrl', require('./controller/app/privatekey-upload'));
|
||||
app.controller('PublicKeyImportCtrl', require('./controller/app/publickey-import'));
|
||||
app.controller('ContactsCtrl', require('./controller/app/contacts'));
|
||||
app.controller('AboutCtrl', require('./controller/app/about'));
|
||||
app.controller('DialogCtrl', require('./controller/app/dialog'));
|
||||
|
@ -4,7 +4,7 @@
|
||||
// Controller
|
||||
//
|
||||
|
||||
var ContactsCtrl = function($scope, $q, keychain, pgp, dialog) {
|
||||
var ContactsCtrl = function($scope, $q, keychain, pgp, dialog, appConfig) {
|
||||
|
||||
//
|
||||
// scope state
|
||||
@ -13,10 +13,13 @@ var ContactsCtrl = function($scope, $q, keychain, pgp, dialog) {
|
||||
$scope.state.contacts = {
|
||||
toggle: function(to) {
|
||||
$scope.state.lightbox = (to) ? 'contacts' : undefined;
|
||||
$scope.searchText = undefined;
|
||||
return $scope.listKeys();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.whiteoutKeyServer = appConfig.config.cloudUrl.replace(/http[s]?:\/\//, ''); // display key server hostname
|
||||
|
||||
//
|
||||
// scope functions
|
||||
//
|
||||
@ -33,6 +36,7 @@ var ContactsCtrl = function($scope, $q, keychain, pgp, dialog) {
|
||||
keys.forEach(function(key) {
|
||||
var params = pgp.getKeyParams(key.publicKey);
|
||||
_.extend(key, params);
|
||||
key.fullUserId = key.userIds[0].name + ' <' + key.userIds[0].emailAddress + '>';
|
||||
});
|
||||
$scope.keys = keys;
|
||||
|
||||
@ -46,39 +50,6 @@ var ContactsCtrl = function($scope, $q, keychain, pgp, dialog) {
|
||||
$scope.fingerprint = formatted;
|
||||
};
|
||||
|
||||
$scope.importKey = function(publicKeyArmored) {
|
||||
var keyParams, pubkey;
|
||||
|
||||
// verifiy public key string
|
||||
if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
|
||||
dialog.error({
|
||||
showBugReporter: false,
|
||||
message: 'Invalid public key!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
keyParams = pgp.getKeyParams(publicKeyArmored);
|
||||
} catch (e) {
|
||||
dialog.error(new Error('Error reading public key params!'));
|
||||
return;
|
||||
}
|
||||
|
||||
pubkey = {
|
||||
_id: keyParams._id,
|
||||
userId: keyParams.userId,
|
||||
userIds: keyParams.userIds,
|
||||
publicKey: publicKeyArmored,
|
||||
imported: true // mark manually imported keys
|
||||
};
|
||||
|
||||
return keychain.saveLocalPublicKey(pubkey).then(function() {
|
||||
// update displayed keys
|
||||
return $scope.listKeys();
|
||||
}).catch(dialog.error);
|
||||
};
|
||||
|
||||
$scope.removeKey = function(key) {
|
||||
return keychain.removeLocalPublicKey(key._id).then(function() {
|
||||
// update displayed keys
|
||||
|
@ -37,6 +37,7 @@ var DialogCtrl = function($scope, dialog) {
|
||||
$scope.title = options.title;
|
||||
$scope.message = options.errMsg || options.message;
|
||||
$scope.faqLink = options.faqLink;
|
||||
$scope.faqLinkTitle = options.faqLinkTitle || 'Learn more';
|
||||
$scope.positiveBtnStr = options.positiveBtnStr || 'Ok';
|
||||
$scope.negativeBtnStr = options.negativeBtnStr || 'Cancel';
|
||||
$scope.showNegativeBtn = options.showNegativeBtn || false;
|
||||
|
78
src/js/controller/app/publickey-import.js
Normal file
78
src/js/controller/app/publickey-import.js
Normal file
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
//
|
||||
// Controller
|
||||
//
|
||||
|
||||
var PublickeyImportCtrl = function($scope, $q, keychain, pgp, hkp, dialog, appConfig) {
|
||||
|
||||
//
|
||||
// scope state
|
||||
//
|
||||
|
||||
$scope.state.publickeyImport = {
|
||||
toggle: function(to) {
|
||||
$scope.state.lightbox = (to) ? 'publickey-import' : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// scope variables
|
||||
//
|
||||
|
||||
$scope.hkpUrl = appConfig.config.hkpUrl.replace('https://', '');
|
||||
|
||||
//
|
||||
// scope functions
|
||||
//
|
||||
|
||||
$scope.importKey = function(publicKeyArmored) {
|
||||
var keyParams, pubkey;
|
||||
|
||||
// verifiy public key string
|
||||
if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
|
||||
dialog.error({
|
||||
showBugReporter: false,
|
||||
message: 'Invalid public key!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
keyParams = pgp.getKeyParams(publicKeyArmored);
|
||||
} catch (e) {
|
||||
dialog.error(new Error('Error reading public key params!'));
|
||||
return;
|
||||
}
|
||||
|
||||
pubkey = {
|
||||
_id: keyParams._id,
|
||||
userId: keyParams.userId,
|
||||
userIds: keyParams.userIds,
|
||||
publicKey: publicKeyArmored,
|
||||
imported: true // mark manually imported keys
|
||||
};
|
||||
|
||||
return keychain.saveLocalPublicKey(pubkey).then(function() {
|
||||
$scope.pastedKey = '';
|
||||
// display success message
|
||||
return dialog.info({
|
||||
title: 'Success',
|
||||
message: 'Public key ' + keyParams._id + ' for ' + keyParams.userId + ' imported successfully!'
|
||||
});
|
||||
}).catch(dialog.error);
|
||||
};
|
||||
|
||||
$scope.lookupKey = function(query) {
|
||||
var keyUrl = hkp.getIndexUrl(query);
|
||||
|
||||
return dialog.info({
|
||||
title: 'Link',
|
||||
message: 'Follow this link and paste the PGP key block above...',
|
||||
faqLink: keyUrl,
|
||||
faqLinkTitle: keyUrl
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = PublickeyImportCtrl;
|
@ -206,6 +206,14 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
||||
return;
|
||||
}
|
||||
|
||||
if (recipient.address) {
|
||||
// display only email address after autocomplete
|
||||
recipient.displayId = recipient.address;
|
||||
} else {
|
||||
// set address after manual input
|
||||
recipient.address = recipient.displayId;
|
||||
}
|
||||
|
||||
// set display to insecure while fetching keys
|
||||
recipient.key = undefined;
|
||||
recipient.secure = false;
|
||||
@ -231,11 +239,12 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
||||
}).then(function(key) {
|
||||
if (key) {
|
||||
// compare again since model could have changed during the roundtrip
|
||||
var matchingUserId = _.findWhere(key.userIds, {
|
||||
var userIds = pgp.getKeyParams(key.publicKey).userIds;
|
||||
var matchingUserId = _.findWhere(userIds, {
|
||||
emailAddress: recipient.address
|
||||
});
|
||||
// compare either primary userId or (if available) multiple IDs
|
||||
if (key.userId === recipient.address || matchingUserId) {
|
||||
if (matchingUserId) {
|
||||
recipient.key = key;
|
||||
recipient.secure = true;
|
||||
}
|
||||
@ -264,7 +273,10 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
||||
function check(recipient) {
|
||||
// validate address
|
||||
if (!util.validateEmailAddress(recipient.address)) {
|
||||
return;
|
||||
return dialog.info({
|
||||
title: 'Warning',
|
||||
message: 'Invalid recipient address!'
|
||||
});
|
||||
}
|
||||
numReceivers++;
|
||||
if (!recipient.secure) {
|
||||
@ -393,8 +405,10 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
||||
// populate address book cache
|
||||
return keychain.listLocalPublicKeys().then(function(keys) {
|
||||
$scope.addressBookCache = keys.map(function(key) {
|
||||
var name = pgp.getKeyParams(key.publicKey).userIds[0].name;
|
||||
return {
|
||||
address: key.userId
|
||||
address: key.userId,
|
||||
displayId: name + ' - ' + key.userId
|
||||
};
|
||||
});
|
||||
});
|
||||
@ -402,7 +416,7 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
||||
}).then(function() {
|
||||
// filter the address book cache
|
||||
return $scope.addressBookCache.filter(function(i) {
|
||||
return i.address.indexOf(query) !== -1;
|
||||
return i.displayId.toLowerCase().indexOf(query.toLowerCase()) !== -1;
|
||||
});
|
||||
|
||||
}).catch(dialog.error);
|
||||
|
19
src/js/service/hkp.js
Normal file
19
src/js/service/hkp.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var ngModule = angular.module('woServices');
|
||||
ngModule.service('hkp', HKP);
|
||||
module.exports = HKP;
|
||||
|
||||
function HKP(appConfig) {
|
||||
this._appConfig = appConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a url of the link to be opened in a new window
|
||||
* @param {String} query Either the email address or name
|
||||
* @return {String} The url of the hkp query
|
||||
*/
|
||||
HKP.prototype.getIndexUrl = function(query) {
|
||||
var baseUrl = this._appConfig.config.hkpUrl + '/pks/lookup?op=index&search=';
|
||||
return baseUrl + encodeURIComponent(query);
|
||||
};
|
@ -9,6 +9,7 @@ require('./newsletter');
|
||||
require('./oauth');
|
||||
require('./privatekey');
|
||||
require('./publickey');
|
||||
require('./hkp');
|
||||
require('./admin');
|
||||
require('./lawnchair');
|
||||
require('./devicestorage');
|
||||
|
@ -117,13 +117,13 @@ Keychain.prototype.refreshKeyForUserId = function(options) {
|
||||
|
||||
// checks if the user's key has been revoked by looking up the key id
|
||||
function checkKeyExists(localKey) {
|
||||
return self._publicKeyDao.get(localKey._id).then(function(cloudKey) {
|
||||
return self._publicKeyDao.getByUserId(userId).then(function(cloudKey) {
|
||||
if (cloudKey && cloudKey._id === localKey._id) {
|
||||
// the key is present on the server, all is well
|
||||
return localKey;
|
||||
}
|
||||
// the key has changed, update the key
|
||||
return updateKey(localKey);
|
||||
return updateKey(localKey, cloudKey);
|
||||
|
||||
}).catch(function(err) {
|
||||
if (err && err.code === 42) {
|
||||
@ -134,24 +134,14 @@ Keychain.prototype.refreshKeyForUserId = function(options) {
|
||||
});
|
||||
}
|
||||
|
||||
function updateKey(localKey) {
|
||||
// look for an updated key for the user id
|
||||
return self._publicKeyDao.getByUserId(userId).then(function(newKey) {
|
||||
// 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
|
||||
return permissionGranted(localKey, newKey);
|
||||
} else {
|
||||
return requestPermission(localKey, newKey);
|
||||
}
|
||||
|
||||
}).catch(function(err) {
|
||||
// offline?
|
||||
if (err && err.code === 42) {
|
||||
return localKey;
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
function updateKey(localKey, newKey) {
|
||||
// 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
|
||||
return permissionGranted(localKey, newKey);
|
||||
} else {
|
||||
return requestPermission(localKey, newKey);
|
||||
}
|
||||
}
|
||||
|
||||
function requestPermission(localKey, newKey) {
|
||||
@ -196,6 +186,7 @@ Keychain.prototype.getReceiverPublicKey = function(userId) {
|
||||
|
||||
// search local keyring for public key
|
||||
return self._lawnchairDAO.list(DB_PUBLICKEY, 0, null).then(function(allPubkeys) {
|
||||
var userIds;
|
||||
// query primary email address
|
||||
var pubkey = _.findWhere(allPubkeys, {
|
||||
userId: userId
|
||||
@ -203,7 +194,8 @@ Keychain.prototype.getReceiverPublicKey = function(userId) {
|
||||
// query mutliple userIds (for imported public keys)
|
||||
if (!pubkey) {
|
||||
for (var i = 0, match; i < allPubkeys.length; i++) {
|
||||
match = _.findWhere(allPubkeys[i].userIds, {
|
||||
userIds = self._pgp.getKeyParams(allPubkeys[i].publicKey).userIds;
|
||||
match = _.findWhere(userIds, {
|
||||
emailAddress: userId
|
||||
});
|
||||
if (match) {
|
||||
|
@ -62,11 +62,12 @@ RestDAO.prototype.get = function(options) {
|
||||
/**
|
||||
* POST (create) request
|
||||
*/
|
||||
RestDAO.prototype.post = function(item, uri) {
|
||||
RestDAO.prototype.post = function(item, uri, type) {
|
||||
return this._processRequest({
|
||||
method: 'POST',
|
||||
payload: item,
|
||||
uri: uri
|
||||
uri: uri,
|
||||
type: type
|
||||
});
|
||||
};
|
||||
|
||||
@ -98,27 +99,32 @@ RestDAO.prototype.remove = function(uri) {
|
||||
RestDAO.prototype._processRequest = function(options) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr, format;
|
||||
var xhr, format, accept, payload;
|
||||
|
||||
if (typeof options.uri === 'undefined') {
|
||||
throw createError(400, 'Bad Request! URI is a mandatory parameter.');
|
||||
}
|
||||
|
||||
options.type = options.type || 'json';
|
||||
payload = options.payload;
|
||||
|
||||
if (options.type === 'json') {
|
||||
format = 'application/json';
|
||||
payload = payload ? JSON.stringify(payload) : undefined;
|
||||
} else if (options.type === 'xml') {
|
||||
format = 'application/xml';
|
||||
} else if (options.type === 'text') {
|
||||
format = 'text/plain';
|
||||
} else if (options.type === 'form') {
|
||||
format = 'application/x-www-form-urlencoded; charset=UTF-8';
|
||||
accept = 'text/html; charset=UTF-8';
|
||||
} else {
|
||||
throw createError(400, 'Bad Request! Unhandled data type.');
|
||||
}
|
||||
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open(options.method, self._baseUri + options.uri);
|
||||
xhr.setRequestHeader('Accept', format);
|
||||
xhr.setRequestHeader('Accept', accept || format);
|
||||
xhr.setRequestHeader('Content-Type', format);
|
||||
|
||||
xhr.onload = function() {
|
||||
@ -146,7 +152,7 @@ RestDAO.prototype._processRequest = function(options) {
|
||||
reject(createError(42, 'Error calling ' + options.method + ' on ' + options.uri));
|
||||
};
|
||||
|
||||
xhr.send(options.payload ? JSON.stringify(options.payload) : undefined);
|
||||
xhr.send(payload);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -123,6 +123,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border: 1px solid $color-border-light;
|
||||
resize: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Attention: Webkit support only!
|
||||
.input-select {
|
||||
position: relative;
|
||||
|
@ -6,10 +6,9 @@
|
||||
</button>
|
||||
</header>
|
||||
<div class="lightbox__content">
|
||||
<input class="u-hide-visually" id="keyfile-input" type="file" multiple accept=".asc" keyfile-input>
|
||||
<div class="form-input-with-button u-gap-bottom">
|
||||
<input class="input-text" type="text" placeholder="Search..." ng-model="searchText">
|
||||
<button class="btn" ng-class="{'btn--invalid': sendBtnSecure === false}" wo-click-file-input="#keyfile-input">Import keys</button>
|
||||
<button class="btn" wo-touch="state.contacts.toggle(false); state.publickeyImport.toggle(true)">Import keys</button>
|
||||
</div>
|
||||
|
||||
<p class="typo-paragraph u-text-center" ng-show="!keys.length">
|
||||
@ -17,7 +16,7 @@
|
||||
</p>
|
||||
|
||||
<ul class="contacts">
|
||||
<li class="contacts__contact" ng-repeat="key in keys | orderBy:'userId' | filter:searchText"
|
||||
<li class="contacts__contact" ng-repeat="key in keys | orderBy:'fullUserId' | filter:searchText"
|
||||
ng-class="{ 'contacts__contact--open': key.open }">
|
||||
<div class="contacts__delete">
|
||||
<button class="btn-icon-very-light" wo-touch="removeKey(key)">
|
||||
@ -25,7 +24,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h3 class="contacts__title" wo-touch="key.open = !key.open">{{key.userId}}</h3>
|
||||
<h3 class="contacts__title" wo-touch="key.open = !key.open">{{key.fullUserId}}</h3>
|
||||
<p class="contacts__short-description">
|
||||
{{key._id.slice(8)}}
|
||||
</p>
|
||||
@ -38,6 +37,9 @@
|
||||
|
||||
<dt>Created</dt>
|
||||
<dd>{{key.created | date:'mediumDate'}}</dd>
|
||||
|
||||
<dt>Source</dt>
|
||||
<dd>{{key.imported ? 'Imported' : key.source || whiteoutKeyServer}}</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -27,6 +27,9 @@
|
||||
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'privatekey-upload'}"
|
||||
ng-include="'tpl/privatekey-upload.html'"></div>
|
||||
|
||||
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'publickey-import'}"
|
||||
ng-include="'tpl/publickey-import.html'"></div>
|
||||
|
||||
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'contacts'}"
|
||||
ng-include="'tpl/contacts.html'"></div>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
</header>
|
||||
|
||||
<div class="lightbox__content">
|
||||
<p class="typo-paragraph">{{message}} <a ng-show="faqLink" href="{{faqLink}}" target="_blank">Learn more</a></p>
|
||||
<p class="typo-paragraph">{{message}} <a ng-show="faqLink" href="{{faqLink}}" target="_blank">{{faqLinkTitle}}</a></p>
|
||||
</div>
|
||||
|
||||
<footer class="lightbox__controls">
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
|
||||
<div class="form__row">
|
||||
<input class="input-file" type="file" accept=".asc" file-reader tabindex="1" required>
|
||||
<input class="input-file" type="file" file-reader tabindex="1" required>
|
||||
</div>
|
||||
<div class="form__row">
|
||||
<input class="input-text" type="password" ng-model="passphrase"
|
||||
|
27
src/tpl/publickey-import.html
Normal file
27
src/tpl/publickey-import.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div class="lightbox__body" ng-controller="PublicKeyImportCtrl">
|
||||
<header class="lightbox__header">
|
||||
<h2>Import PGP keys</h2>
|
||||
<button class="lightbox__close" wo-touch="state.publickeyImport.toggle(false)" data-action="lightbox-close">
|
||||
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div class="lightbox__content">
|
||||
<div class="u-gap-bottom">
|
||||
<p class="typo-paragraph">You can import public keys via copy/paste or as .asc files. Use the lookup function to search by name or email address on the key server. <i>Most keys are fetched automatically while reading and writing messages so most users won't need to import keys manually.</i></p>
|
||||
</div>
|
||||
|
||||
<div class="u-gap-bottom">
|
||||
<textarea class="textarea" placeholder="Paste PUBLIC PGP KEY BLOCK here..." ng-model="pastedKey" ng-change="importKey(pastedKey)"></textarea>
|
||||
</div>
|
||||
|
||||
<form class="form-input-with-button u-gap-bottom">
|
||||
<input class="input-text" type="text" placeholder="Lookup on {{hkpUrl}} by name or email address" ng-model="searchText">
|
||||
<button class="btn" type="submit" ng-click="lookupKey(searchText)">Lookup</button>
|
||||
</form>
|
||||
|
||||
<div class="form__row">
|
||||
<input class="input-file" type="file" multiple keyfile-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -17,8 +17,7 @@
|
||||
</div>
|
||||
<label>To:</label>
|
||||
<tags-input class="tags-input" ng-model="to" type="email" tabindex="1" add-on-space="true" add-on-enter="true" enable-editing-last-tag="true"
|
||||
tag-style="tagStyle" display-property="address" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
allowed-tags-pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
|
||||
tag-style="tagStyle" display-property="displayId" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
placeholder="add recipient">
|
||||
<auto-complete source="lookupAddressBook($query)" min-length="1"></auto-complete>
|
||||
</tags-input>
|
||||
@ -27,8 +26,7 @@
|
||||
focus-input-on-click>
|
||||
<label>Cc:</label>
|
||||
<tags-input class="tags-input" ng-model="cc" type="email" tabindex="1" add-on-space="true" add-on-enter="true" enable-editing-last-tag="true"
|
||||
tag-style="tagStyle" display-property="address" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
allowed-tags-pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
|
||||
tag-style="tagStyle" display-property="displayId" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
placeholder="add cc">
|
||||
<auto-complete source="lookupAddressBook($query)" min-length="1"></auto-complete>
|
||||
</tags-input>
|
||||
@ -37,8 +35,7 @@
|
||||
focus-input-on-click>
|
||||
<label>Bcc:</label>
|
||||
<tags-input class="tags-input" ng-model="bcc" type="email" tabindex="1" add-on-space="true" add-on-enter="true" enable-editing-last-tag="true"
|
||||
tag-style="tagStyle" display-property="address" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
allowed-tags-pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
|
||||
tag-style="tagStyle" display-property="displayId" on-tag-added="verify($tag)" on-tag-removed="checkSendStatus()"
|
||||
placeholder="add bcc">
|
||||
<auto-complete source="lookupAddressBook($query)" min-length="1"></auto-complete>
|
||||
</tags-input>
|
||||
|
@ -51,7 +51,11 @@ describe('Contacts Controller unit test', function() {
|
||||
_id: '12345'
|
||||
}]));
|
||||
pgpStub.getKeyParams.returns({
|
||||
fingerprint: 'asdf'
|
||||
fingerprint: 'asdf',
|
||||
userIds: [{
|
||||
name: 'Firstname Lastname',
|
||||
emailAddress: 'first.last@example.com'
|
||||
}]
|
||||
});
|
||||
|
||||
expect(scope.keys).to.not.exist;
|
||||
@ -59,6 +63,7 @@ describe('Contacts Controller unit test', function() {
|
||||
expect(scope.keys.length).to.equal(1);
|
||||
expect(scope.keys[0]._id).to.equal('12345');
|
||||
expect(scope.keys[0].fingerprint).to.equal('asdf');
|
||||
expect(scope.keys[0].fullUserId).to.equal('Firstname Lastname <first.last@example.com>');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -76,65 +81,6 @@ describe('Contacts Controller unit test', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('importKey', function() {
|
||||
it('should work', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
pgpStub.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com',
|
||||
userIds: []
|
||||
});
|
||||
|
||||
keychainStub.saveLocalPublicKey.withArgs({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com',
|
||||
userIds: [],
|
||||
publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||
imported: true
|
||||
}).returns(resolves());
|
||||
|
||||
scope.listKeys = function() {};
|
||||
|
||||
scope.importKey(keyArmored).then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail due to invalid armored key', function() {
|
||||
var keyArmored = '-----BEGIN PGP PRIVATE KEY BLOCK-----';
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should fail due to error in pgp.getKeyParams', function() {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
pgpStub.getKeyParams.throws(new Error('WAT'));
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should fail due to error in keychain.saveLocalPublicKey', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
pgpStub.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com'
|
||||
});
|
||||
|
||||
keychainStub.saveLocalPublicKey.returns(rejects(42));
|
||||
|
||||
scope.importKey(keyArmored).then(function() {
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeKey', function() {
|
||||
it('should work', function(done) {
|
||||
var key = {
|
||||
|
91
test/unit/controller/app/publickey-import-ctrl-test.js
Normal file
91
test/unit/controller/app/publickey-import-ctrl-test.js
Normal file
@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
var PublicKeyImportCtrl = require('../../../../src/js/controller/app/publickey-import'),
|
||||
Keychain = require('../../../../src/js/service/keychain'),
|
||||
PGP = require('../../../../src/js/crypto/pgp'),
|
||||
Dialog = require('../../../../src/js/util/dialog');
|
||||
|
||||
describe('Public Key Import Controller unit test', function() {
|
||||
var scope, ctrl, keychainStub, pgpStub, dialogStub;
|
||||
|
||||
beforeEach(function() {
|
||||
pgpStub = sinon.createStubInstance(PGP);
|
||||
keychainStub = sinon.createStubInstance(Keychain);
|
||||
dialogStub = sinon.createStubInstance(Dialog);
|
||||
|
||||
angular.module('publickey-import', ['woServices']);
|
||||
angular.mock.module('publickey-import');
|
||||
angular.mock.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(PublicKeyImportCtrl, {
|
||||
$scope: scope,
|
||||
$q: window.qMock,
|
||||
keychain: keychainStub,
|
||||
pgp: pgpStub,
|
||||
dialog: dialogStub
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
describe('importKey', function() {
|
||||
it('should work', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
pgpStub.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com',
|
||||
userIds: []
|
||||
});
|
||||
|
||||
keychainStub.saveLocalPublicKey.withArgs({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com',
|
||||
userIds: [],
|
||||
publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||
imported: true
|
||||
}).returns(resolves());
|
||||
|
||||
scope.listKeys = function() {};
|
||||
|
||||
scope.importKey(keyArmored).then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail due to invalid armored key', function() {
|
||||
var keyArmored = '-----BEGIN PGP PRIVATE KEY BLOCK-----';
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should fail due to error in pgp.getKeyParams', function() {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
pgpStub.getKeyParams.throws(new Error('WAT'));
|
||||
|
||||
scope.importKey(keyArmored);
|
||||
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should fail due to error in keychain.saveLocalPublicKey', function(done) {
|
||||
var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----';
|
||||
|
||||
pgpStub.getKeyParams.returns({
|
||||
_id: '12345',
|
||||
userId: 'max@example.com'
|
||||
});
|
||||
|
||||
keychainStub.saveLocalPublicKey.returns(rejects(42));
|
||||
|
||||
scope.importKey(keyArmored).then(function() {
|
||||
expect(dialogStub.error.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -215,6 +215,11 @@ describe('Write controller unit test', function() {
|
||||
}).returns(resolves({
|
||||
userId: 'asdf@example.com'
|
||||
}));
|
||||
pgpMock.getKeyParams.returns({
|
||||
userIds: [{
|
||||
emailAddress: recipient.address
|
||||
}]
|
||||
});
|
||||
|
||||
scope.verify(recipient).then(function() {
|
||||
expect(recipient.key).to.deep.equal({
|
||||
@ -232,15 +237,17 @@ describe('Write controller unit test', function() {
|
||||
address: 'asdf@example.com'
|
||||
};
|
||||
var key = {
|
||||
userId: 'qwer@example.com',
|
||||
userIds: [{
|
||||
emailAddress: 'asdf@example.com'
|
||||
}]
|
||||
userId: 'qwertz@example.com'
|
||||
};
|
||||
|
||||
keychainMock.refreshKeyForUserId.withArgs({
|
||||
userId: recipient.address
|
||||
}).returns(resolves(key));
|
||||
pgpMock.getKeyParams.returns({
|
||||
userIds: [{
|
||||
emailAddress: recipient.address
|
||||
}]
|
||||
});
|
||||
|
||||
scope.verify(recipient).then(function() {
|
||||
expect(recipient.key).to.deep.equal(key);
|
||||
@ -359,12 +366,18 @@ describe('Write controller unit test', function() {
|
||||
userId: 'test@asdf.com',
|
||||
publicKey: 'KEY'
|
||||
}]));
|
||||
pgpMock.getKeyParams.returns({
|
||||
userIds: [{
|
||||
name: 'Bob'
|
||||
}]
|
||||
});
|
||||
|
||||
var result = scope.lookupAddressBook('test');
|
||||
|
||||
result.then(function(response) {
|
||||
expect(response).to.deep.equal([{
|
||||
address: 'test@asdf.com'
|
||||
address: 'test@asdf.com',
|
||||
displayId: 'Bob - test@asdf.com'
|
||||
}]);
|
||||
done();
|
||||
});
|
||||
@ -372,17 +385,17 @@ describe('Write controller unit test', function() {
|
||||
|
||||
it('should work with cache', function(done) {
|
||||
scope.addressBookCache = [{
|
||||
address: 'test@asdf.com'
|
||||
address: 'test@asdf.com',
|
||||
displayId: 'Bob - test@asdf.com'
|
||||
}, {
|
||||
address: 'tes@asdf.com'
|
||||
address: 'tes@asdf.com',
|
||||
displayId: 'Bob - tes@asdf.com'
|
||||
}];
|
||||
|
||||
var result = scope.lookupAddressBook('test');
|
||||
|
||||
result.then(function(response) {
|
||||
expect(response).to.deep.equal([{
|
||||
address: 'test@asdf.com'
|
||||
}]);
|
||||
expect(response).to.deep.equal([scope.addressBookCache[0]]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -112,7 +112,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should not update the key when up to date', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves(oldKey));
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(oldKey));
|
||||
|
||||
keychainDao.refreshKeyForUserId({
|
||||
userId: testUser
|
||||
@ -120,7 +120,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(key).to.to.equal(oldKey);
|
||||
|
||||
expect(getPubKeyStub.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
@ -128,7 +128,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should update key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(newKey));
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -144,7 +143,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
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;
|
||||
@ -155,7 +153,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should update key without approval', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(newKey));
|
||||
lawnchairDaoStub.remove.withArgs('publickey_' + oldKey._id).returns(resolves());
|
||||
lawnchairDaoStub.persist.withArgs('publickey_' + newKey._id, newKey).returns(resolves());
|
||||
@ -167,7 +164,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
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;
|
||||
@ -178,7 +174,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should remove key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -193,7 +189,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(key).to.not.exist;
|
||||
|
||||
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.called).to.be.false;
|
||||
@ -204,7 +199,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should go offline while fetching new key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(rejects({
|
||||
code: 42
|
||||
}));
|
||||
@ -215,7 +210,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(key).to.to.equal(oldKey);
|
||||
|
||||
expect(getPubKeyStub.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
|
||||
expect(lawnchairDaoStub.remove.called).to.be.false;
|
||||
expect(lawnchairDaoStub.persist.called).to.be.false;
|
||||
@ -226,7 +220,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should not remove old key on user rejection', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(newKey));
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -240,7 +234,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(key).to.equal(oldKey);
|
||||
|
||||
expect(getPubKeyStub.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
|
||||
expect(lawnchairDaoStub.remove.called).to.be.false;
|
||||
expect(lawnchairDaoStub.persist.called).to.be.false;
|
||||
@ -266,7 +259,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should update not the key when offline', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(rejects({
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(rejects({
|
||||
code: 42
|
||||
}));
|
||||
|
||||
@ -276,8 +269,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(key).to.to.equal(oldKey);
|
||||
|
||||
expect(getPubKeyStub.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.getByUserId.called).to.be.false;
|
||||
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
|
||||
expect(lawnchairDaoStub.remove.called).to.be.false;
|
||||
expect(lawnchairDaoStub.persist.called).to.be.false;
|
||||
|
||||
@ -287,7 +279,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should error while persisting new key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(newKey));
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -303,7 +295,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(err).to.exist;
|
||||
|
||||
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;
|
||||
@ -314,7 +305,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should error while deleting old key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -328,7 +319,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(err).to.exist;
|
||||
|
||||
expect(getPubKeyStub.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
|
||||
expect(lawnchairDaoStub.remove.calledOnce).to.be.true;
|
||||
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
|
||||
expect(lawnchairDaoStub.persist.called).to.be.false;
|
||||
@ -339,7 +329,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should error while persisting new key', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves());
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(resolves(newKey));
|
||||
keychainDao.requestPermissionForKeyUpdate = function(opts, cb) {
|
||||
expect(opts.userId).to.equal(testUser);
|
||||
@ -355,7 +345,6 @@ describe('Keychain DAO unit tests', function() {
|
||||
expect(err).to.exist;
|
||||
|
||||
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;
|
||||
@ -366,7 +355,7 @@ describe('Keychain DAO unit tests', function() {
|
||||
|
||||
it('should error when get failed', function(done) {
|
||||
getPubKeyStub.returns(resolves(oldKey));
|
||||
pubkeyDaoStub.get.withArgs(oldKey._id).returns(rejects({}));
|
||||
pubkeyDaoStub.getByUserId.withArgs(testUser).returns(rejects({}));
|
||||
|
||||
keychainDao.refreshKeyForUserId({
|
||||
userId: testUser
|
||||
@ -497,11 +486,13 @@ describe('Keychain DAO unit tests', function() {
|
||||
lawnchairDaoStub.list.returns(resolves([{
|
||||
_id: '12345',
|
||||
userId: 'not testUser',
|
||||
userIds: [{
|
||||
emailAddress: testUser
|
||||
}],
|
||||
publicKey: 'asdf'
|
||||
}]));
|
||||
pgpStub.getKeyParams.returns({
|
||||
userIds: [{
|
||||
emailAddress: testUser
|
||||
}]
|
||||
});
|
||||
|
||||
keychainDao.getReceiverPublicKey(testUser).then(function(key) {
|
||||
expect(key).to.exist;
|
||||
|
Loading…
Reference in New Issue
Block a user