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',
|
msg:'This property has not been retrieved yet from GPG',
|
||||||
type: 'error'
|
type: 'error'
|
||||||
},
|
},
|
||||||
|
'KEY_ASYNC_ONLY': {
|
||||||
|
msg: 'This property cannot be used in synchronous calls',
|
||||||
|
type: 'error'
|
||||||
|
},
|
||||||
'KEY_NO_DEFAULT': {
|
'KEY_NO_DEFAULT': {
|
||||||
msg:'A default key could not be established. Please check yout gpg ' +
|
msg:'A default key could not be established. Please check yout gpg ' +
|
||||||
'configuration',
|
'configuration',
|
||||||
|
@ -80,55 +80,31 @@ class GPGME_Key {
|
|||||||
return _data.fingerprint;
|
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}
|
* Query any property of the Key listed in {@link validKeyProperties}
|
||||||
* @param {String} property property to be retreived
|
* @param {String} property property to be retreived
|
||||||
* @returns {*|Promise<*>} the value (Boolean, String, Array, Object).
|
* @returns {Boolean| String | Date | Array | Object |GPGME_Error}
|
||||||
* If 'cached' is false, the value will be resolved as a Promise.
|
* 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) {
|
this.get = function(property) {
|
||||||
if (this.isAsync === true) {
|
if (this.isAsync === true) {
|
||||||
let me = this;
|
switch (property){
|
||||||
return new Promise(function(resolve, reject) {
|
case 'armored':
|
||||||
if (property === 'armored'){
|
return this.getArmor();
|
||||||
resolve(me.getArmor());
|
case 'hasSecret':
|
||||||
} else if (property === 'hasSecret'){
|
return this.getGnupgSecretState();
|
||||||
resolve(me.getHasSecret());
|
default:
|
||||||
} else if (validKeyProperties.hasOwnProperty(property)){
|
return getGnupgState(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'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
|
if (property === 'armored') {
|
||||||
|
return gpgme_error('KEY_ASYNC_ONLY');
|
||||||
|
}
|
||||||
if (!validKeyProperties.hasOwnProperty(property)){
|
if (!validKeyProperties.hasOwnProperty(property)){
|
||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
}
|
|
||||||
if (!_data.hasOwnProperty(property)){
|
|
||||||
return gpgme_error('KEY_NO_INIT');
|
|
||||||
} else {
|
} else {
|
||||||
return (_data[property]);
|
return (_data[property]);
|
||||||
}
|
}
|
||||||
@ -160,7 +136,7 @@ class GPGME_Key {
|
|||||||
reject(gpgme_error('KEY_INVALID'));
|
reject(gpgme_error('KEY_INVALID'));
|
||||||
} else {
|
} else {
|
||||||
_data = newdata;
|
_data = newdata;
|
||||||
me.getHasSecret().then(function(){
|
me.getGnupgSecretState().then(function(){
|
||||||
me.getArmor().then(function(){
|
me.getArmor().then(function(){
|
||||||
resolve(me);
|
resolve(me);
|
||||||
}, function(error){
|
}, function(error){
|
||||||
@ -195,7 +171,6 @@ class GPGME_Key {
|
|||||||
msg.setParameter('armor', true);
|
msg.setParameter('armor', true);
|
||||||
msg.setParameter('keys', _data.fingerprint);
|
msg.setParameter('keys', _data.fingerprint);
|
||||||
msg.post().then(function(result){
|
msg.post().then(function(result){
|
||||||
_data.armored = result.data;
|
|
||||||
resolve(result.data);
|
resolve(result.data);
|
||||||
}, function(error){
|
}, function(error){
|
||||||
reject(error);
|
reject(error);
|
||||||
@ -205,37 +180,38 @@ class GPGME_Key {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out if the Key includes a secret part. Note that this is a
|
* 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
|
* If you want this inforrmation about more than a few Keys, it may be
|
||||||
* advisable to run {@link Keyring.getKeys} instead.
|
* advisable to run {@link Keyring.getKeys} instead.
|
||||||
* @returns {Promise<Boolean|GPGME_Error>} True if a secret/private Key
|
* @returns {Promise<Boolean|GPGME_Error>} True if a secret/private Key
|
||||||
* is available in the gnupg Keyring
|
* is available in the gnupg Keyring
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
this.getHasSecret = function (){
|
this.getGnupgSecretState = function (){
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!_data.fingerprint){
|
if (!_data.fingerprint){
|
||||||
reject(gpgme_error('KEY_INVALID'));
|
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(){
|
get fingerprint(){
|
||||||
return this.getFingerprint();
|
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
|
* 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
|
* @protected
|
||||||
* @const
|
* @const
|
||||||
*/
|
*/
|
||||||
@ -504,9 +490,6 @@ const validKeyProperties = {
|
|||||||
'fingerprint': function(value){
|
'fingerprint': function(value){
|
||||||
return isFingerprint(value);
|
return isFingerprint(value);
|
||||||
},
|
},
|
||||||
'armored': function(value){
|
|
||||||
return typeof(value === 'string');
|
|
||||||
},
|
|
||||||
'revoked': function(value){
|
'revoked': function(value){
|
||||||
return typeof(value) === 'boolean';
|
return typeof(value) === 'boolean';
|
||||||
},
|
},
|
||||||
@ -623,4 +606,75 @@ function validateKeyData(data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return key;
|
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
|
* @param {String | Array<String>} pattern (optional) A pattern to
|
||||||
* search for in userIds or KeyIds.
|
* search for in userIds or KeyIds.
|
||||||
* @param {Boolean} prepare_sync (optional) if set to true, the
|
* @param {Boolean} prepare_sync (optional) if set to true, most data
|
||||||
* 'hasSecret' and 'armored' properties will be fetched for the Keys as
|
* (with the exception of armored Key blocks) will be cached for the
|
||||||
* well. These require additional calls to gnupg, resulting in a
|
* Keys. This enables direct, synchronous use of these properties for
|
||||||
* performance hungry operation. Calling them here enables direct,
|
* all keys. It does not check for changes on the backend. The cached
|
||||||
* synchronous use of these properties for all keys, without having to
|
* information can be updated with the {@link Key.refresh} method.
|
||||||
* resort to a refresh() first.
|
|
||||||
* @param {Boolean} search (optional) retrieve Keys from external
|
* @param {Boolean} search (optional) retrieve Keys from external
|
||||||
* servers with the method(s) defined in gnupg (e.g. WKD/HKP lookup)
|
* servers with the method(s) defined in gnupg (e.g. WKD/HKP lookup)
|
||||||
* @returns {Promise<Array<GPGME_Key>>}
|
* @returns {Promise<Array<GPGME_Key>>}
|
||||||
@ -97,7 +96,6 @@ export class GPGME_Keyring {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO getArmor() to be used in sync
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let k = createKey(result.keys[i].fingerprint,
|
let k = createKey(result.keys[i].fingerprint,
|
||||||
|
@ -304,10 +304,6 @@ function unittests (){
|
|||||||
expect(result).to.be.an('array');
|
expect(result).to.be.an('array');
|
||||||
expect(result[0]).to.be.an.instanceof(GPGME_Key);
|
expect(result[0]).to.be.an.instanceof(GPGME_Key);
|
||||||
expect(result[0].get('hasSecret')).to.be.a('boolean');
|
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();
|
done();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user