js: removed Key.armor property in synchronous use
-- * src/Key.js The synchronous mode for a Key does not offer an armor/ armored property anymore. This frees up a lot of performance issues, also the armored expoort is expected to change quite often, so a cached version is not advisable. * hasSecret/getHasSecret is now refactored, to reflect their uses. With get('hasSecret') there is a method that fetches the result. * src/Key.js also some refactoring
This commit is contained in:
parent
754e799d35
commit
ad39d54d19
@ -81,6 +81,10 @@ const err_list = {
|
||||
msg:'This property has not been retrieved yet from GPG',
|
||||
type: 'error'
|
||||
},
|
||||
'KEY_ASYNC_ONLY': {
|
||||
msg: 'This property cannot be used in synchronous calls',
|
||||
type: 'error'
|
||||
},
|
||||
'KEY_NO_DEFAULT': {
|
||||
msg:'A default key could not be established. Please check yout gpg ' +
|
||||
'configuration',
|
||||
|
@ -80,55 +80,31 @@ class GPGME_Key {
|
||||
return _data.fingerprint;
|
||||
};
|
||||
|
||||
/**
|
||||
* Property indicating if the Key possesses a private/secret part. If
|
||||
* this information is not yet cached, it returns an
|
||||
* {@link GPGME_Error} with code 'KEY_NO_INIT'. Running
|
||||
* {@link refreshKey} may help in this case.
|
||||
* @returns {Boolean} If the Key has a secret subkey.
|
||||
*/
|
||||
this.hasSecret= function (){
|
||||
return this.get('hasSecret');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Query any property of the Key listed in {@link validKeyProperties}
|
||||
* @param {String} property property to be retreived
|
||||
* @returns {*|Promise<*>} the value (Boolean, String, Array, Object).
|
||||
* If 'cached' is false, the value will be resolved as a Promise.
|
||||
* @returns {Boolean| String | Date | Array | Object |GPGME_Error}
|
||||
* the value of the property. If the Key is set to Async, the value
|
||||
* will be fetched from gnupg and resolved as a Promise. If Key is not
|
||||
* async, the armored property is not available (it can still be
|
||||
* retrieved asynchronously by {@link Key.getArmor})
|
||||
*/
|
||||
this.get = function(property) {
|
||||
if (this.isAsync === true) {
|
||||
let me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (property === 'armored'){
|
||||
resolve(me.getArmor());
|
||||
} else if (property === 'hasSecret'){
|
||||
resolve(me.getHasSecret());
|
||||
} else if (validKeyProperties.hasOwnProperty(property)){
|
||||
let msg = createMessage('keylist');
|
||||
msg.setParameter('keys', _data.fingerprint);
|
||||
msg.post().then(function(result){
|
||||
if (result.keys && result.keys.length === 1 &&
|
||||
result.keys[0].hasOwnProperty(property)){
|
||||
resolve(result.keys[0][property]);
|
||||
} else {
|
||||
reject(gpgme_error('CONN_UNEXPECTED_ANSWER'));
|
||||
}
|
||||
}, function(error){
|
||||
reject(gpgme_error(error));
|
||||
});
|
||||
} else {
|
||||
reject(gpgme_error('PARAM_WRONG'));
|
||||
}
|
||||
});
|
||||
switch (property){
|
||||
case 'armored':
|
||||
return this.getArmor();
|
||||
case 'hasSecret':
|
||||
return this.getGnupgSecretState();
|
||||
default:
|
||||
return getGnupgState(property);
|
||||
}
|
||||
} else {
|
||||
if (property === 'armored') {
|
||||
return gpgme_error('KEY_ASYNC_ONLY');
|
||||
}
|
||||
if (!validKeyProperties.hasOwnProperty(property)){
|
||||
return gpgme_error('PARAM_WRONG');
|
||||
}
|
||||
if (!_data.hasOwnProperty(property)){
|
||||
return gpgme_error('KEY_NO_INIT');
|
||||
} else {
|
||||
return (_data[property]);
|
||||
}
|
||||
@ -160,7 +136,7 @@ class GPGME_Key {
|
||||
reject(gpgme_error('KEY_INVALID'));
|
||||
} else {
|
||||
_data = newdata;
|
||||
me.getHasSecret().then(function(){
|
||||
me.getGnupgSecretState().then(function(){
|
||||
me.getArmor().then(function(){
|
||||
resolve(me);
|
||||
}, function(error){
|
||||
@ -195,7 +171,6 @@ class GPGME_Key {
|
||||
msg.setParameter('armor', true);
|
||||
msg.setParameter('keys', _data.fingerprint);
|
||||
msg.post().then(function(result){
|
||||
_data.armored = result.data;
|
||||
resolve(result.data);
|
||||
}, function(error){
|
||||
reject(error);
|
||||
@ -205,37 +180,38 @@ class GPGME_Key {
|
||||
|
||||
/**
|
||||
* Find out if the Key includes a secret part. Note that this is a
|
||||
* rather nonperformant operation, as it needs to query gnupg twice.
|
||||
* rather nonperformant operation.
|
||||
* If you want this inforrmation about more than a few Keys, it may be
|
||||
* advisable to run {@link Keyring.getKeys} instead.
|
||||
* @returns {Promise<Boolean|GPGME_Error>} True if a secret/private Key
|
||||
* is available in the gnupg Keyring
|
||||
* @async
|
||||
*/
|
||||
this.getHasSecret = function (){
|
||||
this.getGnupgSecretState = function (){
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!_data.fingerprint){
|
||||
reject(gpgme_error('KEY_INVALID'));
|
||||
} else {
|
||||
let msg = createMessage('keylist');
|
||||
msg.setParameter('keys', _data.fingerprint);
|
||||
msg.setParameter('secret', true);
|
||||
msg.post().then(function(result){
|
||||
_data.hasSecret = null;
|
||||
if (
|
||||
result.keys &&
|
||||
result.keys.length === 1 &&
|
||||
result.keys[0].secret === true
|
||||
) {
|
||||
_data.hasSecret = true;
|
||||
resolve(true);
|
||||
} else {
|
||||
_data.hasSecret = false;
|
||||
resolve(false);
|
||||
}
|
||||
}, function(error){
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
let msg = createMessage('keylist');
|
||||
msg.setParameter('keys', _data.fingerprint);
|
||||
msg.setParameter('secret', true);
|
||||
msg.post().then(function(result){
|
||||
_data.hasSecret = null;
|
||||
if (
|
||||
result.keys &&
|
||||
result.keys.length === 1 &&
|
||||
result.keys[0].secret === true
|
||||
) {
|
||||
_data.hasSecret = true;
|
||||
resolve(true);
|
||||
} else {
|
||||
_data.hasSecret = false;
|
||||
resolve(false);
|
||||
}
|
||||
}, function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -262,25 +238,11 @@ class GPGME_Key {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The fingerprint defining this Key
|
||||
* @returns {String} The fingerprint defining this Key. Convenience getter
|
||||
*/
|
||||
get fingerprint(){
|
||||
return this.getFingerprint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Property for the export of armored Key. If the armored Key is not
|
||||
* cached, it returns an {@link GPGME_Error} with code 'KEY_NO_INIT'.
|
||||
* Running {@link refreshKey} may help in this case.
|
||||
* @returns {String|GPGME_Error} The armored public Key block.
|
||||
*/
|
||||
get armored(){
|
||||
if (this.isAsync === true){
|
||||
return gpgme_error('KEY_NO_INIT');
|
||||
} else {
|
||||
return this.get('armored');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -496,7 +458,31 @@ const validSubKeyProperties = {
|
||||
|
||||
/**
|
||||
* Validation definition for Keys. Each valid Key property is represented
|
||||
* as a key-value pair, with their value being a validation function
|
||||
* as a key-value pair, with their value being a validation function. For
|
||||
* details on the meanings, please refer to the gpgme documentation
|
||||
* https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html#Key-objects
|
||||
* @param {String} fingerprint
|
||||
* @param {Boolean} revoked
|
||||
* @param {Boolean} expired
|
||||
* @param {Boolean} disabled
|
||||
* @param {Boolean} invalid
|
||||
* @param {Boolean} can_encrypt
|
||||
* @param {Boolean} can_sign
|
||||
* @param {Boolean} can_certify
|
||||
* @param {Boolean} can_authenticate
|
||||
* @param {Boolean} secret
|
||||
* @param {Boolean}is_qualified
|
||||
* @param {String} protocol
|
||||
* @param {String} issuer_serial
|
||||
* @param {String} issuer_name
|
||||
* @param {Boolean} chain_id
|
||||
* @param {String} owner_trust
|
||||
* @param {Date} last_update
|
||||
* @param {String} origin
|
||||
* @param {Array<GPGME_Subkey>} subkeys
|
||||
* @param {Array<GPGME_UserId>} userids
|
||||
* @param {Array<String>} tofu
|
||||
* @param {Boolean} hasSecret
|
||||
* @protected
|
||||
* @const
|
||||
*/
|
||||
@ -504,9 +490,6 @@ const validKeyProperties = {
|
||||
'fingerprint': function(value){
|
||||
return isFingerprint(value);
|
||||
},
|
||||
'armored': function(value){
|
||||
return typeof(value === 'string');
|
||||
},
|
||||
'revoked': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
@ -623,4 +606,75 @@ function validateKeyData(data){
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches and sets properties from gnupg
|
||||
* @param {String} fingerprint
|
||||
* @param {String} property to search for.
|
||||
* @private
|
||||
* @async
|
||||
*/
|
||||
function getGnupgState (fingerprint, property){
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!isFingerprint(fingerprint)) {
|
||||
reject(gpgme_error('KEY_INVALID'));
|
||||
} else {
|
||||
let msg = createMessage('keylist');
|
||||
msg.setParameter('keys', fingerprint);
|
||||
msg.post().then(function(result){
|
||||
if (!result.keys || result.keys.length !== 1){
|
||||
reject(gpgme_error('KEY_INVALID'));
|
||||
} else {
|
||||
const key = result.keys[0];
|
||||
let result;
|
||||
switch (property){
|
||||
case 'subkeys':
|
||||
result = [];
|
||||
if (key.subkeys.length){
|
||||
for (let i=0; i < key.subkeys.length; i++) {
|
||||
result.push(Object.freeze(
|
||||
new GPGME_Subkey(key.subkeys[i])));
|
||||
}
|
||||
}
|
||||
resolve(result);
|
||||
break;
|
||||
case 'userids':
|
||||
result = [];
|
||||
if (key.userids.length){
|
||||
for (let i=0; i< key.userids.length; i++) {
|
||||
result.push(Object.freeze(
|
||||
new GPGME_UserId(key.userids[i])));
|
||||
}
|
||||
}
|
||||
resolve(result);
|
||||
break;
|
||||
case 'last_update':
|
||||
if (key.last_update === undefined){
|
||||
reject(gpgme_error('CONN_UNEXPECTED_ANSWER'));
|
||||
} else if (key.last_update !== null){
|
||||
resolve(new Date( key.last_update * 1000));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!validKeyProperties.hasOwnProperty(property)){
|
||||
reject(gpgme_error('PARAM_WRONG'));
|
||||
} else {
|
||||
if (key.hasOwnProperty(property)){
|
||||
resolve(key[property]);
|
||||
} else {
|
||||
reject(gpgme_error(
|
||||
'CONN_UNEXPECTED_ANSWER'));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, function(error){
|
||||
reject(gpgme_error(error));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
@ -38,12 +38,11 @@ export class GPGME_Keyring {
|
||||
*
|
||||
* @param {String | Array<String>} pattern (optional) A pattern to
|
||||
* search for in userIds or KeyIds.
|
||||
* @param {Boolean} prepare_sync (optional) if set to true, the
|
||||
* 'hasSecret' and 'armored' properties will be fetched for the Keys as
|
||||
* well. These require additional calls to gnupg, resulting in a
|
||||
* performance hungry operation. Calling them here enables direct,
|
||||
* synchronous use of these properties for all keys, without having to
|
||||
* resort to a refresh() first.
|
||||
* @param {Boolean} prepare_sync (optional) if set to true, most data
|
||||
* (with the exception of armored Key blocks) will be cached for the
|
||||
* Keys. This enables direct, synchronous use of these properties for
|
||||
* all keys. It does not check for changes on the backend. The cached
|
||||
* information can be updated with the {@link Key.refresh} method.
|
||||
* @param {Boolean} search (optional) retrieve Keys from external
|
||||
* servers with the method(s) defined in gnupg (e.g. WKD/HKP lookup)
|
||||
* @returns {Promise<Array<GPGME_Key>>}
|
||||
@ -97,7 +96,6 @@ export class GPGME_Keyring {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO getArmor() to be used in sync
|
||||
}
|
||||
}
|
||||
let k = createKey(result.keys[i].fingerprint,
|
||||
|
@ -304,10 +304,6 @@ function unittests (){
|
||||
expect(result).to.be.an('array');
|
||||
expect(result[0]).to.be.an.instanceof(GPGME_Key);
|
||||
expect(result[0].get('hasSecret')).to.be.a('boolean');
|
||||
// TODO: preparing sync for armored is still in discussion
|
||||
// expect(result[0].get('armored')).to.be.a('string');
|
||||
// expect(result[0].get('armored')).to.include(
|
||||
// '-----END PGP PUBLIC KEY BLOCK-----');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user