diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index 0fd9c43ae..a7d93aa6e 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -83,10 +83,10 @@ if (0 === aResult.length && Utils.isNonEmptyArray(aRecipients)) { - aResult = _.compact(_.flatten(_.map(aRecipients, function (sEmail) { - var oKey = sEmail ? self.findPrivateKeyByEmailNotNative(sEmail) : null; - return oKey ? (bReturnWrapKeys ? [oKey] : oKey.getNativeKeys()) : [null]; - }), true)); + aResult = _.uniq(_.compact(_.flatten(_.map(aRecipients, function (sEmail) { + var aKeys = sEmail ? self.findAllPrivateKeysByEmailNotNative(sEmail) : null; + return aKeys ? (bReturnWrapKeys ? aKeys : _.flatten(_.map(aKeys, function (oKey) { return oKey.getNativeKeys(); }), true)) : [null]; + }), true)), function (oKey) { return oKey.id; }); } return aResult; @@ -114,6 +114,28 @@ }) || null; }; + /** + * @param {string} sEmail + * @return {?} + */ + PgpUserStore.prototype.findAllPublicKeysByEmailNotNative = function (sEmail) + { + return _.filter(this.openpgpkeysPublic(), function (oItem) { + return oItem && -1 !== oItem.emails.indexOf(sEmail); + }) || null; + }; + + /** + * @param {string} sEmail + * @return {?} + */ + PgpUserStore.prototype.findAllPrivateKeysByEmailNotNative = function (sEmail) + { + return _.filter(this.openpgpkeysPrivate(), function (oItem) { + return oItem && -1 !== oItem.emails.indexOf(sEmail); + }) || null; + }; + /** * @param {string} sEmail * @param {string=} sPassword diff --git a/dev/View/Popup/ComposeOpenPgp.js b/dev/View/Popup/ComposeOpenPgp.js index 80a782d45..44205c7e4 100644 --- a/dev/View/Popup/ComposeOpenPgp.js +++ b/dev/View/Popup/ComposeOpenPgp.js @@ -30,7 +30,8 @@ var self = this; - this.optionsCaption = Translator.i18n('PGP_NOTIFICATIONS/ADD_A_PUBLICK_KEY'); + this.publicKeysOptionsCaption = Translator.i18n('PGP_NOTIFICATIONS/ADD_A_PUBLICK_KEY'); + this.privateKeysOptionsCaption = Translator.i18n('PGP_NOTIFICATIONS/SELECT_A_PRIVATE_KEY'); this.notification = ko.observable(''); @@ -42,6 +43,7 @@ this.buttonFocus = ko.observable(false); this.text = ko.observable(''); + this.selectedPrivateKey = ko.observable(null); this.selectedPublicKey = ko.observable(null); this.signKey = ko.observable(null); @@ -53,6 +55,20 @@ })); }, this); + this.privateKeysOptions = ko.computed(function () { + return _.compact(_.flatten(_.map(PgpStore.openpgpkeysPrivate(), function (oKey, iIndex) { + return self.signKey() && self.signKey().key.id === oKey.id ? null : + _.map(oKey.users, function (sUser) { + return { + 'id': oKey.guid, + 'name': '(' + oKey.id.substr(-8).toUpperCase() + ') ' + sUser, + 'key': oKey, + 'class': iIndex % 2 ? 'odd' : 'even' + }; + }); + }), true)); + }); + this.publicKeysOptions = ko.computed(function () { return _.compact(_.flatten(_.map(PgpStore.openpgpkeysPublic(), function (oKey, iIndex) { return -1 < Utils.inArray(oKey, self.encryptKeysView()) ? null : @@ -225,6 +241,31 @@ return !this.submitRequest() && (this.sign() || this.encrypt()); }); + this.selectCommand = Utils.createCommand(this, function () { + + var + sKeyId = this.selectedPrivateKey(), + oKey = null, + aKeys = this.encryptKeys(), + oOption = sKeyId ? _.find(this.privateKeysOptions(), function (oItem) { + return oItem && sKeyId === oItem.id; + }) : null + ; + + if (oOption) + { + oKey = { + 'empty': !oOption.key, + 'selected': ko.observable(!!oOption.key), + 'users': oOption.key.users, + 'hash': oOption.key.id.substr(-8).toUpperCase(), + 'key': oOption.key + }; + + this.signKey(oKey); + } + }); + this.addCommand = Utils.createCommand(this, function () { var @@ -240,7 +281,7 @@ aKeys.push({ 'empty': !oOption.key, 'selected': ko.observable(!!oOption.key), - 'removable': this.signKey().id !== oOption.key.id, + 'removable': ko.observable(!this.sign() || !this.signKey() || this.signKey().key.id !== oOption.key.id), 'users': oOption.key.users, 'hash': oOption.key.id.substr(-8).toUpperCase(), 'key': oOption.key @@ -250,6 +291,24 @@ } }); + this.updateCommand = Utils.createCommand(this, function () { + + var self = this; + + _.each(this.encryptKeys(), function (oKey) { + oKey.removable(!self.sign() || !self.signKey() || self.signKey().key.id !== oKey.key.id); + }); + + }); + + this.selectedPrivateKey.subscribe(function (sValue) { + if (sValue) + { + this.selectCommand(); + this.updateCommand(); + } + }, this); + this.selectedPublicKey.subscribe(function (sValue) { if (sValue) { @@ -342,8 +401,10 @@ this.clearPopup(); var + self = this, aRec = [], sEmail = '', + aKeys = [], oKey = null, oEmail = new EmailModel() ; @@ -376,9 +437,10 @@ { sEmail = oIdentity.email(); aRec.unshift(sEmail); - oKey = PgpStore.findPrivateKeyByEmailNotNative(sEmail); - if (oKey) + aKeys = PgpStore.findAllPrivateKeysByEmailNotNative(sEmail); + if (aKeys) { + var oKey = aKeys[0]; this.signKey({ 'users': oKey.users || [sEmail], 'hash': oKey.id.substr(-8).toUpperCase(), @@ -394,17 +456,19 @@ if (aRec && 0 < aRec.length) { - this.encryptKeys(_.uniq(_.compact(_.map(aRec, function (sEmail) { - var oKey = PgpStore.findPublicKeyByEmailNotNative(sEmail) || null; - return { - 'empty': !oKey, - 'selected': ko.observable(!!oKey), - 'removable': oIdentity && oIdentity.email() && oIdentity.email() !== sEmail, - 'users': oKey ? (oKey.users || [sEmail]) : [sEmail], - 'hash': oKey ? oKey.id.substr(-8).toUpperCase() : '', - 'key': oKey - }; - })), function (oEncryptKey) { + this.encryptKeys(_.uniq(_.compact(_.flatten(_.map(aRec, function (sEmail) { + var aKeys = PgpStore.findAllPublicKeysByEmailNotNative(sEmail); + return aKeys ? _.map(aKeys, function (oKey) { + return { + 'empty': !oKey, + 'selected': ko.observable(!!oKey), + 'removable': ko.observable(!self.sign() || !self.signKey() || self.signKey().key.id !== oKey.id), + 'users': oKey ? (oKey.users || [sEmail]) : [sEmail], + 'hash': oKey ? oKey.id.substr(-8).toUpperCase() : '', + 'key': oKey + }; + }) : []; + }), true)), function (oEncryptKey) { return oEncryptKey.hash; })); diff --git a/rainloop/v/0.0.0/app/localization/webmail/_source.en.yml b/rainloop/v/0.0.0/app/localization/webmail/_source.en.yml index 057ca2aad..e2cb9d7c7 100644 --- a/rainloop/v/0.0.0/app/localization/webmail/_source.en.yml +++ b/rainloop/v/0.0.0/app/localization/webmail/_source.en.yml @@ -620,6 +620,7 @@ en: NO_PRIVATE_KEY_FOUND: "No private key found" NO_PRIVATE_KEY_FOUND_FOR: "No private key found for \"%EMAIL%\" email" ADD_A_PUBLICK_KEY: "Add a public key" + SELECT_A_PRIVATE_KEY: "Select a private key" UNVERIFIRED_SIGNATURE: "Unverified signature" DECRYPTION_ERROR: "OpenPGP decryption error" GOOD_SIGNATURE: "Good signature from %USER%" diff --git a/rainloop/v/0.0.0/app/templates/Views/User/PopupsComposeOpenPgp.html b/rainloop/v/0.0.0/app/templates/Views/User/PopupsComposeOpenPgp.html index 7ea3d0d1c..52329813d 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/PopupsComposeOpenPgp.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/PopupsComposeOpenPgp.html @@ -20,23 +20,23 @@ label: 'POPUPS_COMPOSE_OPEN_PGP/LABEL_SIGN', value: sign } - }"> + }, click: updateCommand ">