aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lang/js/src/Errors.js4
-rw-r--r--lang/js/src/Key.js218
-rw-r--r--lang/js/src/Keyring.js12
-rw-r--r--lang/js/unittests.js4
4 files changed, 145 insertions, 93 deletions
diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js
index 39e3a74a..b22eca73 100644
--- a/lang/js/src/Errors.js
+++ b/lang/js/src/Errors.js
@@ -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',
diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js
index 8d7fd948..5d0c8160 100644
--- a/lang/js/src/Key.js
+++ b/lang/js/src/Key.js
@@ -81,54 +81,30 @@ class GPGME_Key {
};
/**
- * 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));
+ });
+ }
+ });
} \ No newline at end of file
diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js
index 43ab96c8..766bab15 100644
--- a/lang/js/src/Keyring.js
+++ b/lang/js/src/Keyring.js
@@ -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,
diff --git a/lang/js/unittests.js b/lang/js/unittests.js
index 3304b1eb..25023bcb 100644
--- a/lang/js/unittests.js
+++ b/lang/js/unittests.js
@@ -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();
}
);