js: more testing
[gpgme.git] / lang / js / src / Key.js
1 /* gpgme.js - Javascript integration for gpgme
2  * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * GPGME is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  * SPDX-License-Identifier: LGPL-2.1+
19  */
20
21 /**
22  * The key class allows to query the information defined in gpgme Key Objects
23  * (see https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html)
24  *
25  * This is a stub, as the gpgme-json side is not yet implemented
26  *
27  */
28
29 import { isFingerprint } from './Helpers'
30 import { gpgme_error } from './Errors'
31 import { createMessage } from './Message';
32 import { permittedOperations } from './permittedOperations';
33
34 export class GPGME_Key {
35
36     constructor(fingerprint){
37         this.fingerprint = fingerprint;
38     }
39
40     set fingerprint(fpr){
41         if (isFingerprint(fpr) === true && !this._fingerprint){
42             this._fingerprint = fpr;
43         }
44     }
45
46     get fingerprint(){
47         return this._fingerprint;
48     }
49
50     /**
51      * hasSecret returns true if a secret subkey is included in this Key
52      */
53     get hasSecret(){
54         return checkKey(this._fingerprint, 'secret');
55     }
56
57     get isRevoked(){
58         return checkKey(this._fingerprint, 'revoked');
59     }
60
61     get isExpired(){
62         return checkKey(this._fingerprint, 'expired');
63     }
64
65     get isDisabled(){
66         return checkKey(this._fingerprint, 'disabled');
67     }
68
69     get isInvalid(){
70         return checkKey(this._fingerprint, 'invalid');
71     }
72
73     get canEncrypt(){
74         return checkKey(this._fingerprint, 'can_encrypt');
75     }
76
77     get canSign(){
78         return checkKey(this._fingerprint, 'can_sign');
79     }
80
81     get canCertify(){
82         return checkKey(this._fingerprint, 'can_certify');
83     }
84
85     get canAuthenticate(){
86         return checkKey(this._fingerprint, 'can_authenticate');
87     }
88
89     get isQualified(){
90         return checkKey(this._fingerprint, 'is_qualified');
91     }
92
93     get armored(){
94         let me = this;
95         return new Promise(function(resolve, reject){
96             let conn = new Connection();
97             conn.setFlag('armor', true);
98             conn.post('export',{'fpr': me._fingerprint});
99         });
100         // TODO return value not yet checked. Should result in an armored block
101         // in correct encoding
102         // TODO openpgpjs also returns secKey if private = true?
103     }
104
105     /**
106      * TODO returns true if this is the default key used to sign
107      */
108     get isDefault(){
109         throw('NOT_YET_IMPLEMENTED');
110     }
111
112     /**
113      * get the Key's subkeys as GPGME_Key objects
114      * @returns {Array<GPGME_Key>}
115      */
116     get subkeys(){
117         return checkKey(this._fingerprint, 'subkeys').then(function(result){
118             // TBD expecting a list of fingerprints
119             if (!Array.isArray(result)){
120                 result = [result];
121             }
122             let resultset = [];
123             for (let i=0; i < result.length; i++){
124                 let subkey = new GPGME_Key(result[i]);
125                 if (subkey instanceof GPGME_Key){
126                     resultset.push(subkey);
127                 }
128             }
129             return Promise.resolve(resultset);
130         }, function(error){
131             //TODO checkKey fails
132         });
133     }
134
135     /**
136      * creation time stamp of the key
137      * @returns {Date|null} TBD
138      */
139     get timestamp(){
140         return checkKey(this._fingerprint, 'timestamp');
141         //TODO GPGME: -1 if the timestamp is invalid, and 0 if it is not available.
142     }
143
144     /**
145      * The expiration timestamp of this key TBD
146      *  @returns {Date|null} TBD
147      */
148     get expires(){
149         return checkKey(this._fingerprint, 'expires');
150         // TODO convert to Date; check for 0
151     }
152
153     /**
154      * getter name TBD
155      * @returns {String|Array<String>} The user ids associated with this key
156      */
157     get userIds(){
158         return checkKey(this._fingerprint, 'uids');
159     }
160
161     /**
162      * @returns {String} The public key algorithm supported by this subkey
163      */
164     get pubkey_algo(){
165         return checkKey(this._fingerprint, 'pubkey_algo');
166     }
167 };
168
169 /**
170  * generic function to query gnupg information on a key.
171  * @param {*} fingerprint The identifier of the Keyring
172  * @param {*} property The gpgme-json property to check
173  *
174  */
175 function checkKey(fingerprint, property){
176     return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
177     if (!property || !permittedOperations[keyinfo].hasOwnProperty(property)){
178             return Promise.reject(gpgme_error('PARAM_WRONG'));
179     }
180     return new Promise(function(resolve, reject){
181         if (!isFingerprint(fingerprint)){
182             reject(gpgme_error('KEY_INVALID'));
183         }
184         let msg = createMessage ('keyinfo');
185         if (msg instanceof Error){
186             reject(gpgme_error('PARAM_WRONG'));
187         }
188         msg.setParameter('fingerprint', this.fingerprint);
189         return (this.connection.post(msg)).then(function(result, error){
190             if (error){
191                 reject(gpgme_error('GNUPG_ERROR',error.msg));
192             } else if (result.hasOwnProperty(property)){
193                 resolve(result[property]);
194             }
195             else if (property == 'secret'){
196                     // TBD property undefined means "not true" in case of secret?
197                     resolve(false);
198             } else {
199                 reject(gpgme_error('CONN_UNEXPECTED_ANSWER'));
200             }
201         }, function(error){
202             //TODO error handling
203         });
204     });
205 };