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