diff options
Diffstat (limited to 'lang/js')
| -rw-r--r-- | lang/js/.babelrc | 1 | ||||
| -rw-r--r-- | lang/js/package.json | 6 | ||||
| -rw-r--r-- | lang/js/src/Connection.js | 2 | ||||
| -rw-r--r-- | lang/js/src/Errors.js | 11 | ||||
| -rw-r--r-- | lang/js/src/Helpers.js | 7 | ||||
| -rw-r--r-- | lang/js/src/Key.js | 15 | ||||
| -rw-r--r-- | lang/js/src/Keyring.js | 7 | ||||
| -rw-r--r-- | lang/js/src/Message.js | 47 | ||||
| -rw-r--r-- | lang/js/src/gpgmejs.js | 31 | ||||
| -rw-r--r-- | lang/js/test/Helpers.js | 110 | ||||
| -rw-r--r-- | lang/js/test/Message.js | 42 | ||||
| -rw-r--r-- | lang/js/test/mocha.opts | 4 | 
12 files changed, 227 insertions, 56 deletions
| diff --git a/lang/js/.babelrc b/lang/js/.babelrc new file mode 100644 index 00000000..9d8d5165 --- /dev/null +++ b/lang/js/.babelrc @@ -0,0 +1 @@ +{ "presets": ["es2015"] } diff --git a/lang/js/package.json b/lang/js/package.json index 2b7dd7ee..a794188a 100644 --- a/lang/js/package.json +++ b/lang/js/package.json @@ -5,13 +5,15 @@    "main": "src/index.js",    "private": true,    "scripts": { -    "test": "echo \"Error: no test specified\" && exit 1" +    "test": "mocha"    },    "keywords": [],    "author": "",    "license": "",    "devDependencies": {      "webpack": "^4.5.0", -    "webpack-cli": "^2.0.14" +    "webpack-cli": "^2.0.14", +    "chai": "^4.1.2", +    "mocha": "^5.1.1"    }  } diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 5b092ab0..a10f9d9a 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -83,7 +83,7 @@ export class Connection{       */      post(message){          if (!this.isConnected){ -            return Promise.reject(gpgme_error('CONN_NO_CONNECT')); +            return Promise.reject(gpgme_error('CONN_DISCONNECTED'));          }          if (!message || !message instanceof GPGME_Message){              return Promise.reject(gpgme_error('PARAM_WRONG'), message); diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js index 2f53aa89..d26aab18 100644 --- a/lang/js/src/Errors.js +++ b/lang/js/src/Errors.js @@ -55,14 +55,9 @@ const err_list = {          msg: 'The Message is empty.',          type: 'error'      }, -    'MSG_OP_PENDING': { -        msg: 'There is no operation specified yet. The parameter cannot' -            + ' be set', -        type: 'warning' -    },      'MSG_WRONG_OP': {          msg: 'The operation requested could not be found', -        type: 'warning' +        type: 'error'      },      'MSG_NO_KEYS' : {          msg: 'There were no valid keys provided.', @@ -78,7 +73,7 @@ const err_list = {      },      // generic      'PARAM_WRONG':{ -        msg: 'invalid parameter was found', +        msg: 'Invalid parameter was found',          type: 'error'      },      'PARAM_IGNORED': { @@ -111,7 +106,7 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){              return new GPGME_Error(code);          }          if (err_list[code].type === 'warning'){ -            console.log(new GPGME_Error(code)); +            console.warn(code + ': ' + err_list[code].msg);          }          return null;      } else if (code === 'GNUPG_ERROR'){ diff --git a/lang/js/src/Helpers.js b/lang/js/src/Helpers.js index 841c0eda..9a69f851 100644 --- a/lang/js/src/Helpers.js +++ b/lang/js/src/Helpers.js @@ -18,6 +18,7 @@   * SPDX-License-Identifier: LGPL-2.1+   */  import { gpgme_error } from "./Errors"; +import { GPGME_Key } from "./Key";  /**   * Tries to return an array of fingerprints, either from input fingerprints or @@ -26,7 +27,7 @@ import { gpgme_error } from "./Errors";   * @returns {Array<String>} Array of fingerprints.   */ -export function toKeyIdArray(input, nocheck){ +export function toKeyIdArray(input){      if (!input){          gpgme_error('MSG_NO_KEYS');          return []; @@ -46,7 +47,7 @@ export function toKeyIdArray(input, nocheck){              let fpr = '';              if (input[i] instanceof GPGME_Key){                  fpr = input[i].fingerprint; -            } else if (input[i].hasOwnProperty(primaryKey) && +            } else if (input[i].hasOwnProperty('primaryKey') &&                  input[i].primaryKey.hasOwnProperty(getFingerprint)){                      fpr = input[i].primaryKey.getFingerprint();              } @@ -92,7 +93,7 @@ export function isFingerprint(string){  /**   * check if the input is a valid Hex string with a length of 16   */ -function isLongId(string){ +export function isLongId(string){      return hextest(string, 16);  }; diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index f6fa7ae3..0b44b245 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -26,9 +26,9 @@   *   */ -import {isFingerprint} from './Helpers' -import {gpgme_error} from './Errors' -import { GPGME_Message } from './Message'; +import { isFingerprint } from './Helpers' +import { gpgme_error } from './Errors' +import { createMessage } from './Message';  import { permittedOperations } from './permittedOperations';  export class GPGME_Key { @@ -39,7 +39,7 @@ export class GPGME_Key {      set fingerprint(fpr){          if (isFingerprint(fpr) === true && !this._fingerprint){ -            this._fingerprint = fingerprint; +            this._fingerprint = fpr;          }      } @@ -181,9 +181,12 @@ function checkKey(fingerprint, property){      }      return new Promise(function(resolve, reject){          if (!isFingerprint(fingerprint)){ -            reject('KEY_INVALID'); +            reject(gpgme_error('KEY_INVALID')); +        } +        let msg = createMessage ('keyinfo'); +        if (msg instanceof Error){ +            reject(gpgme_error('PARAM_WRONG'));          } -        let msg = new GPGME_Message('keyinfo');          msg.setParameter('fingerprint', this.fingerprint);          return (this.connection.post(msg)).then(function(result){              if (result.hasOwnProperty(property)){ diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index e1f0a50f..470eeeec 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -18,7 +18,7 @@   * SPDX-License-Identifier: LGPL-2.1+   */ -import {GPGME_Message} from './Message' +import {createMessage} from './Message'  import {GPGME_Key} from './Key'  import { isFingerprint, isLongId } from './Helpers';  import { gpgme_error } from './Errors'; @@ -50,7 +50,10 @@ export class GPGME_Keyring {       *       */      getKeys(pattern, include_secret){ -        let msg = new GPGME_Message('listkeys'); +        let msg = createMessage('listkeys'); +        if (msg instanceof Error){ +            return Promise.reject(msg); +        }          if (pattern && typeof(pattern) === 'string'){              msg.setParameter('pattern', pattern);          } diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 06ac8db2..4d242277 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -19,13 +19,34 @@   */  import { permittedOperations } from './permittedOperations'  import { gpgme_error } from './Errors' -export class GPGME_Message { + +export function createMessage(operation){ +    if (typeof(operation) !== 'string'){ +        return gpgme_error('PARAM_WRONG'); +    } +    if (permittedOperations.hasOwnProperty(operation)){ +        return new GPGME_Message(operation); +    } else { +        return gpgme_error('MSG_WRONG_OP'); +    } +} + +/** + * Prepares a communication request. It checks operations and parameters in + * ./permittedOperations. + * @param {String} operation + */ +class GPGME_Message {      //TODO getter      constructor(operation){ -        setOperation(this, operation); +        this.operation = operation;      } +    set operation (op){ + + +    }      get operation(){          return this._msg.op;      } @@ -41,9 +62,6 @@ export class GPGME_Message {          if (!param || typeof(param) !== 'string'){              return gpgme_error('PARAM_WRONG');          } -        if (!this._msg || !this._msg.op){ -            return gpgme_error('MSG_OP_PENDING'); -        }          let po = permittedOperations[this._msg.op];          if (!po){              return gpgme_error('MSG_WRONG_OP'); @@ -90,22 +108,3 @@ export class GPGME_Message {      }  } - -/** - * Defines the operation this message will have - * @param {String} operation Must be defined in permittedOperations - *  TODO: move to constructor? - */ -function setOperation (scope, operation){ -    if (!operation || typeof(operation) !== 'string'){ -        return gpgme_error('PARAM_WRONG'); -    } -    if (permittedOperations.hasOwnProperty(operation)){ -        if (!scope._msg){ -            scope._msg = {}; -        } -        scope._msg.op = operation; -    } else { -        return gpgme_error('MSG_WRONG_OP'); -    } -}
\ No newline at end of file diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index b504a457..2ddf2964 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -19,7 +19,7 @@   */  import {Connection} from "./Connection" -import {GPGME_Message} from './Message' +import {GPGME_Message, createMessage} from './Message'  import {toKeyIdArray} from "./Helpers"  import { gpgme_error } from "./Errors"  import { GPGME_Keyring } from "./Keyring"; @@ -71,8 +71,10 @@ export class GpgME {       */      encrypt(data, publicKeys, wildcard=false){ -        let msg = new GPGME_Message('encrypt'); - +        let msg = createMessage('encrypt'); +        if (msg instanceof Error){ +            return Promise.reject(msg) +        }          // TODO temporary          msg.setParameter('armor', true);          msg.setParameter('always-trust', true); @@ -101,7 +103,10 @@ export class GpgME {          if (data === undefined){              return Promise.reject(gpgme_error('MSG_EMPTY'));          } -        let msg = new GPGME_Message('decrypt'); +        let msg = createMessage('decrypt'); +        if (msg instanceof Error){ +            return Promise.reject(msg); +        }          putData(msg, data);          return this.connection.post(msg); @@ -109,21 +114,27 @@ export class GpgME {      deleteKey(key, delete_secret = false, no_confirm = false){          return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED')); -        let msg = new GPGME_Message('deletekey'); +        let msg = createMessage('deletekey'); +        if (msg instanceof Error){ +            return Promise.reject(msg); +        }          let key_arr = toKeyIdArray(key);          if (key_arr.length !== 1){ -            throw('TODO'); -            //should always be ONE key +            return Promise.reject( +                gpgme_error('GENERIC_ERROR')); +            // TBD should always be ONE key?          }          msg.setParameter('key', key_arr[0]);          if (delete_secret === true){ -            msg.setParameter('allow_secret', true); //TBD +            msg.setParameter('allow_secret', true); +            // TBD          }          if (no_confirm === true){ //TODO: Do we want this hidden deep in the code? -            msg.setParameter('delete_force', true); //TBD +            msg.setParameter('delete_force', true); +            // TBD          }          this.connection.post(msg).then(function(success){ -            //TODO: it seems that there is always errors coming back: +            // TODO: it seems that there is always errors coming back:          }, function(error){              switch (error.msg){              case 'ERR_NO_ERROR': diff --git a/lang/js/test/Helpers.js b/lang/js/test/Helpers.js new file mode 100644 index 00000000..590f9f65 --- /dev/null +++ b/lang/js/test/Helpers.js @@ -0,0 +1,110 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +import { expect } from "../node_modules/chai/chai"; +import { gpgme_error} from "../src/Errors"; +import { GPGME_Key } from "../src/Key"; +import { isLongId, isFingerprint, toKeyIdArray } from "../src/Helpers" + +const helper_params = { +    validLongId: '0A0A0A0A0A0A0A0A', +    validGPGME_Key: new GPGME_Key('ADDBC303B6D31026F5EB4591A27EABDF283121BB'), +    validKeys: [new GPGME_Key('A1E3BC45BDC8E87B74F4392D53B151A1368E50F3'), +        'ADDBC303B6D31026F5EB4591A27EABDF283121BB', +        new GPGME_Key('EE17AEE730F88F1DE7713C54BBE0A4FF7851650A')], +    validFingerprint: '9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A', +    invalidLongId: '9A9A7A7A8A9A9A7A7A8A', +    invalidFingerprint: [{hello:'World'}], +    invalidKeyArray: {curiosity:'uncat'}, +    invalidKeyArray_OneBad: [ +        new GPGME_Key('12AE9F3E41B33BF77DF52B6BE8EE1992D7909B08'), +        'E1D18E6E994FA9FE9360Bx0E687B940FEFEB095A', +        '3AEA7FE4F5F416ED18CEC63DD519450D9C0FAEE5'], +    invalidErrorCode: 'Please type in all your passwords.' +} + +describe('Error Object handling', function(){ +    it('check the Timeout error', function(){ +        let test0 = gpgme_error('CONN_TIMEOUT'); +        expect(test0).to.be.an.instanceof(Error); +        expect(test0.code).to.equal('CONN_TIMEOUT'); +    }); +    it('Error Object returns generic code if code is not listed', function(){ +        let test0 = gpgme_error(helper_params.invalidErrorCode); +        expect(test0).to.be.an.instanceof(Error); +        expect(test0.code).to.equal('GENERIC_ERROR'); +    }); + +    it('Warnings like PARAM_IGNORED should not return errors', function(){ +        let test0 = gpgme_error('PARAM_IGNORED'); +        expect(test0).to.be.null; +    }); +}); + +describe('Fingerprint checking', function(){ +    it('isFingerprint(): valid Fingerprint', function(){ +        let test0  = isFingerprint(helper_params.validFingerprint); +        expect(test0).to.be.true; +    }); +    it('isFingerprint(): invalid Fingerprint', function(){ +        let test0 = isFingerprint(helper_params.invalidFingerprint); +        expect(test0).to.be.false; +    }); +}); +describe('Converting to Fingerprint', function(){ +    it('Correct Inputs', function(){ +        it('Fingerprint string', function(){ +            let test0 = toKeyIdArray(helper_params.validFingerprint); +            expect(test0).to.be.an('array'); +            expect(test0).to.include(helper_params.validFingerprint); +        }); +        it('GPGME_Key', function(){ +            expect(helper_params.validGPGME_Key).to.be.an.instanceof(GPGME_Key); +            let test0 = toKeyIdArray(helper_params.validGPGME_Key); +            expect(test0).to.be.an('array'); +            expect(test0).to.include(helper_params.validGPGME_Key.fingerprint); +        }); +        it('Array of valid inputs', function(){ +            let test0 = toKeyIdArray(helper_params.validKeys); +            expect(test0).to.be.an('array'); +            expect(test0).to.have.lengthOf(helper_params.validKeys.length); +        }); +    }); +    describe('Incorrect inputs', function(){ +        it('valid Long ID', function(){ +            let test0 = toKeyIdArray(helper_params.validLongId); +            expect(test0).to.be.empty; +        }); +        it('invalidFingerprint', function(){ +            let test0 = toKeyIdArray(helper_params.invalidFingerprint); +            expect(test0).to.be.empty; +        }); +        it('invalidKeyArray', function(){ +            let test0 = toKeyIdArray(helper_params.invalidKeyArray); +            expect(test0).to.be.empty; +        }); +        it('Partially invalid array', function(){ +            let test0 = toKeyIdArray(helper_params.invalidKeyArray_OneBad); +            expect(test0).to.be.an('array'); +            expect(test0).to.have.lengthOf( +                helper_params.invalidKeyArray_OneBad.length - 1); +        }); +    }); +}); diff --git a/lang/js/test/Message.js b/lang/js/test/Message.js new file mode 100644 index 00000000..454b8ca3 --- /dev/null +++ b/lang/js/test/Message.js @@ -0,0 +1,42 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +import { expect } from "../node_modules/chai/chai"; +import { GPGME_Message, createMessage } from "../src/Message"; + +const message_params = { +    invalid_op_action : 'dance', +    invalid_op_type : [234, 34, '<>'], +} + +describe('Message Object', function(){ +    describe('incorrect initialization', function(){ +        it('non-allowed operation', function(){ +            let test0 = createMessage(message_params.invalid_op_action); +            expect(test0).to.be.an.instanceof(Error); +            expect(test0.code).to.equal('MSG_WRONG_OP'); +        }); +        it('wrong parameter type in constructor', function(){ +            let test0 = createMessage(message_params.invalid_op_type); +            expect(test0).to.be.an.instanceof(Error); +            expect(test0.code).to.equal('PARAM_WRONG'); +        }); +    }); +}); diff --git a/lang/js/test/mocha.opts b/lang/js/test/mocha.opts new file mode 100644 index 00000000..65adc1c3 --- /dev/null +++ b/lang/js/test/mocha.opts @@ -0,0 +1,4 @@ +--require babel-register +--reporter spec +--ui bdd +--colors | 
