js: Configuration and Error handling
[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 { GPGME_Message } 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 = fingerprint;
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         checkKey(this._fingerprint, 'secret').then( function(result){
55             return Promise.resolve(result);
56         });
57
58     }
59
60     get isRevoked(){
61         return checkKey(this._fingerprint, 'revoked');
62     }
63
64     get isExpired(){
65         return checkKey(this._fingerprint, 'expired');
66     }
67
68     get isDisabled(){
69         return checkKey(this._fingerprint, 'disabled');
70     }
71
72     get isInvalid(){
73         return checkKey(this._fingerprint, 'invalid');
74     }
75
76     get canEncrypt(){
77         return checkKey(this._fingerprint, 'can_encrypt');
78     }
79
80     get canSign(){
81         return checkKey(this._fingerprint, 'can_sign');
82     }
83
84     get canCertify(){
85         return checkKey(this._fingerprint, 'can_certify');
86     }
87
88     get canAuthenticate(){
89         return checkKey(this._fingerprint, 'can_authenticate');
90     }
91
92     get isQualified(){
93         return checkKey(this._fingerprint, 'is_qualified');
94     }
95
96     get armored(){
97         let me = this;
98         return new Promise(function(resolve, reject){
99             let conn = new Connection();
100             conn.setFlag('armor', true);
101             conn.post('export',{'fpr': me._fingerprint});
102         });
103         // TODO return value not yet checked. Should result in an armored block
104         // in correct encoding
105         // TODO openpgpjs also returns secKey if private = true?
106     }
107
108     /**
109      * TODO returns true if this is the default key used to sign
110      */
111     get isDefault(){
112         throw('NOT_YET_IMPLEMENTED');
113     }
114
115     /**
116      * get the Key's subkeys as GPGME_Key objects
117      * @returns {Array<GPGME_Key>}
118      */
119     get subkeys(){
120         return checkKey(this._fingerprint, 'subkeys').then(function(result){
121             // TBD expecting a list of fingerprints
122             if (!Array.isArray(result)){
123                 result = [result];
124             }
125             let resultset = [];
126             for (let i=0; i < result.length; i++){
127                 let subkey = new GPGME_Key(result[i]);
128                 if (subkey instanceof GPGME_Key){
129                     resultset.push(subkey);
130                 }
131             }
132             return Promise.resolve(resultset);
133         });
134     }
135
136     /**
137      * creation time stamp of the key
138      * @returns {Date|null} TBD
139      */
140     get timestamp(){
141         return checkKey(this._fingerprint, 'timestamp');
142         //TODO GPGME: -1 if the timestamp is invalid, and 0 if it is not available.
143     }
144
145     /**
146      * The expiration timestamp of this key TBD
147      *  @returns {Date|null} TBD
148      */
149     get expires(){
150         return checkKey(this._fingerprint, 'expires');
151         // TODO convert to Date; check for 0
152     }
153
154     /**
155      * getter name TBD
156      * @returns {String|Array<String>} The user ids associated with this key
157      */
158     get userIds(){
159         return checkKey(this._fingerprint, 'uids');
160     }
161
162     /**
163      * @returns {String} The public key algorithm supported by this subkey
164      */
165     get pubkey_algo(){
166         return checkKey(this._fingerprint, 'pubkey_algo');
167     }
168 };
169
170 /**
171  * generic function to query gnupg information on a key.
172  * @param {*} fingerprint The identifier of the Keyring
173  * @param {*} property The gpgme-json property to check
174  *
175  */
176 function checkKey(fingerprint, property){
177     return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
178     if (!property ||
179         permittedOperations[keyinfo].indexOf(property) < 0){
180             return Promise.reject(gpgme_error('PARAM_WRONG'));
181     }
182     return new Promise(function(resolve, reject){
183         if (!isFingerprint(fingerprint)){
184             reject('KEY_INVALID');
185         }
186         let msg = new GPGME_Message('keyinfo');
187         msg.setParameter('fingerprint', this.fingerprint);
188         return (this.connection.post(msg)).then(function(result){
189             if (result.hasOwnProperty(property)){
190                 resolve(result[property]);
191             }
192             else if (property == 'secret'){
193                 // TBD property undefined means "not true" in case of secret?
194                 resolve(false);
195             } else {
196                 reject(gpgme_error('CONN_UNEXPECTED_ANSWER'));
197             }
198         }, function(error){
199             reject({code: 'GNUPG_ERROR',
200                          msg: error.msg});
201         });
202     });
203 };