secrez 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +503 -444
  2. package/bin/secrez.js +50 -47
  3. package/coverage.report +91 -85
  4. package/package.json +10 -12
  5. package/src/Command.js +78 -57
  6. package/src/PreCommand.js +75 -70
  7. package/src/Welcome.js +144 -134
  8. package/src/cliConfig.js +14 -14
  9. package/src/commands/Alias.js +123 -100
  10. package/src/commands/Bash.js +10 -12
  11. package/src/commands/Cat.js +117 -107
  12. package/src/commands/Cd.js +39 -42
  13. package/src/commands/Chat.js +75 -63
  14. package/src/commands/Conf.js +123 -99
  15. package/src/commands/Contacts.js +189 -171
  16. package/src/commands/Copy.js +132 -113
  17. package/src/commands/Courier.js +123 -105
  18. package/src/commands/Ds.js +88 -76
  19. package/src/commands/Edit.js +122 -103
  20. package/src/commands/Export.js +201 -116
  21. package/src/commands/Find.js +115 -110
  22. package/src/commands/Help.js +20 -23
  23. package/src/commands/Import.js +296 -225
  24. package/src/commands/Lcat.js +36 -39
  25. package/src/commands/Lcd.js +38 -39
  26. package/src/commands/Lls.js +58 -55
  27. package/src/commands/Lpwd.js +20 -24
  28. package/src/commands/Ls.js +107 -97
  29. package/src/commands/Mkdir.js +35 -38
  30. package/src/commands/Mv.js +147 -114
  31. package/src/commands/Paste.js +68 -65
  32. package/src/commands/Pwd.js +18 -23
  33. package/src/commands/Quit.js +22 -24
  34. package/src/commands/Rm.js +78 -70
  35. package/src/commands/Shell.js +31 -32
  36. package/src/commands/Ssh.js +77 -63
  37. package/src/commands/Tag.js +133 -112
  38. package/src/commands/Totp.js +166 -136
  39. package/src/commands/Touch.js +169 -56
  40. package/src/commands/Use.js +44 -41
  41. package/src/commands/Ver.js +16 -18
  42. package/src/commands/Whoami.js +34 -37
  43. package/src/commands/chat/Contacts.js +41 -44
  44. package/src/commands/chat/Help.js +20 -23
  45. package/src/commands/chat/Join.js +59 -55
  46. package/src/commands/chat/Leave.js +16 -22
  47. package/src/commands/chat/Quit.js +19 -24
  48. package/src/commands/chat/Send.js +58 -57
  49. package/src/commands/chat/Show.js +60 -51
  50. package/src/commands/chat/Whoami.js +18 -22
  51. package/src/commands/index.js +20 -22
  52. package/src/index.js +3 -3
  53. package/src/prompts/ChatPrompt.js +87 -82
  54. package/src/prompts/ChatPromptMock.js +11 -17
  55. package/src/prompts/CommandPrompt.js +146 -138
  56. package/src/prompts/Completion.js +64 -69
  57. package/src/prompts/MainPrompt.js +84 -77
  58. package/src/prompts/MainPromptMock.js +19 -30
  59. package/src/prompts/MultiEditorPrompt.js +21 -22
  60. package/src/prompts/SigintManager.js +21 -24
  61. package/src/utils/AliasManager.js +16 -18
  62. package/src/utils/ContactManager.js +15 -17
  63. package/src/utils/Fido2Client.js +59 -49
  64. package/src/utils/HelpProto.js +130 -117
  65. package/src/utils/Logger.js +48 -50
  66. package/.eslintignore +0 -0
  67. package/.eslintrc +0 -33
  68. package/.jshintrc +0 -3
@@ -1,197 +1,282 @@
1
- const fs = require('fs-extra')
2
- const path = require('path')
3
- const chalk = require('chalk')
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
+ const chalk = require("chalk");
4
4
 
5
- const Crypto = require('@secrez/crypto')
6
- const {sleep} = require('@secrez/utils')
7
-
8
- const {Node, FileCipher} = require('@secrez/fs')
9
-
10
- class Export extends require('../Command') {
5
+ const Crypto = require("@secrez/crypto");
6
+ const { sleep, yamlParse } = require("@secrez/utils");
7
+ const { encryptPrivateKeyAsKeystoreJson } = require("@secrez/eth");
8
+ const { Node, FileCipher } = require("@secrez/fs");
11
9
 
10
+ class Export extends require("../Command") {
12
11
  setHelpAndCompletion() {
13
12
  this.cliConfig.completion.export = {
14
13
  _func: this.selfCompletion(this),
15
- _self: this
16
- }
17
- this.cliConfig.completion.help.export = true
14
+ _self: this,
15
+ };
16
+ this.cliConfig.completion.help.export = true;
18
17
  this.optionDefinitions = [
19
18
  {
20
- name: 'help',
21
- alias: 'h',
22
- type: Boolean
19
+ name: "help",
20
+ alias: "h",
21
+ type: Boolean,
23
22
  },
24
23
  {
25
- name: 'path',
26
- completionType: 'file',
27
- alias: 'p',
24
+ name: "path",
25
+ completionType: "file",
26
+ alias: "p",
28
27
  defaultOption: true,
29
- type: String
28
+ type: String,
30
29
  },
31
30
  {
32
- name: 'version',
33
- alias: 'v',
34
- type: Boolean
31
+ name: "version",
32
+ alias: "v",
33
+ type: Boolean,
35
34
  },
36
35
  {
37
- name: 'duration',
38
- alias: 'd',
39
- type: Number
36
+ name: "duration",
37
+ alias: "d",
38
+ type: Number,
40
39
  },
41
40
  {
42
- name: 'encrypt',
43
- alias: 'e',
44
- type: Boolean
41
+ name: "encrypt",
42
+ alias: "e",
43
+ type: Boolean,
45
44
  },
46
45
  {
47
- name: 'contacts',
48
- alias: 'c',
46
+ name: "contacts",
47
+ alias: "c",
49
48
  multiple: true,
50
- type: String
49
+ type: String,
51
50
  },
52
51
  {
53
- name: 'public-keys',
52
+ name: "public-keys",
54
53
  multiple: true,
55
- type: String
54
+ type: String,
56
55
  },
57
56
  {
58
- name: 'password',
59
- type: String
57
+ name: "password",
58
+ type: String,
60
59
  },
61
60
  {
62
- name: 'include-me',
63
- type: Boolean
64
- }
65
- ]
61
+ name: "include-me",
62
+ type: Boolean,
63
+ },
64
+ {
65
+ name: "keystore",
66
+ alias: "k",
67
+ type: Boolean,
68
+ },
69
+ ];
66
70
  }
67
71
 
68
72
  help() {
69
73
  return {
70
74
  description: [
71
- 'Export encrypted data to the OS in the current local folder',
72
- 'Files and folders are decrypted during the process.'
75
+ "Export encrypted data to the OS in the current local folder",
76
+ "Files and folders are decrypted during the process.",
73
77
  ],
74
78
  examples: [
75
- ['export seed.json', 'decrypts and copies seed.json to the disk'],
76
- ['export seed.json -d 30', 'export seed.json and remove it from disk after 30 seconds'],
77
- ['export ethKeys -v 8uW3', 'exports version 8uW3 of the file'],
78
- ['export seed.json -e', 'asks for a password and encrypts seed.json before exporting it. The final file will have the extension ".secrez"'],
79
- ['export seed.json -e --password "some strong password"', 'uses the typed password to encrypt seed.json before exporting it'],
80
- ['export seed.json -ec bob alice', 'encrypts seed.json using a key shared with the contacts Bob and Alice, before exporting it'],
81
- ['export seed.json -e --public-keys TCpDvTiVpHwNiS....', 'encrypts seed.json using shared keys generated from the specified public keys'],
82
- ['export seed.json -e --include-me', 'encrypts seed.json also using your key'],
83
- ]
84
- }
79
+ ["export seed.json", "decrypts and copies seed.json to the disk"],
80
+ [
81
+ "export seed.json -d 30",
82
+ "export seed.json and remove it from disk after 30 seconds",
83
+ ],
84
+ ["export ethKeys -v 8uW3", "exports version 8uW3 of the file"],
85
+ [
86
+ "export seed.json -e",
87
+ 'asks for a password and encrypts seed.json before exporting it. The final file will have the extension ".secrez"',
88
+ ],
89
+ [
90
+ 'export seed.json -e --password "some strong password"',
91
+ "uses the typed password to encrypt seed.json before exporting it",
92
+ ],
93
+ [
94
+ "export seed.json -ec bob alice",
95
+ "encrypts seed.json using a key shared with the contacts Bob and Alice, before exporting it",
96
+ ],
97
+ [
98
+ "export seed.json -e --public-keys TCpDvTiVpHwNiS....",
99
+ "encrypts seed.json using shared keys generated from the specified public keys",
100
+ ],
101
+ [
102
+ "export seed.json -e --include-me",
103
+ "encrypts seed.json also using your key",
104
+ ],
105
+ [
106
+ "export my-wallet.yml -k",
107
+ "it will export a private key from the entry to a keystore file. The fill will be named as the entry replacing the extension with '.keystore.json'. If in the entry there are more than one private_key, it will ask which one to export. If no '--password' is specified, it will ask for a password to encrypt the keystore file. The entry must be a valid card, with at least one 'private_key' field.",
108
+ ],
109
+ ],
110
+ };
85
111
  }
86
112
 
87
113
  async export(options = {}) {
88
- let efs = this.externalFs
89
- let fileCipher = new FileCipher(this.secrez)
90
- let cat = this.prompt.commands.cat
91
- let lpwd = this.prompt.commands.lpwd
92
- let originalPath = options.path
93
- let data = await this.internalFs.getTreeIndexAndPath(options.path)
94
- options.path = data.path
95
- let tree = data.tree
96
- let p = tree.getNormalizedPath(options.path)
97
- let file = tree.root.getChildFromPath(p)
114
+ let efs = this.externalFs;
115
+ let fileCipher = new FileCipher(this.secrez);
116
+ let cat = this.prompt.commands.cat;
117
+ let lpwd = this.prompt.commands.lpwd;
118
+ let originalPath = options.path;
119
+ let data = await this.internalFs.getTreeIndexAndPath(options.path);
120
+ options.path = data.path;
121
+ let tree = data.tree;
122
+ let p = tree.getNormalizedPath(options.path);
123
+ let file = tree.root.getChildFromPath(p);
98
124
  if (Node.isFile(file)) {
99
- let entry = (await cat.cat({
100
- path: originalPath,
101
- version: options.version,
102
- unformatted: true
103
- }))[0]
104
- let dir = await lpwd.lpwd()
105
- let newPath = path.join(dir, path.basename(p) + (options.encrypt ? '.secrez' + (Node.isBinary(entry) ? 'b' : '') : ''))
106
- let name = await efs.getVersionedBasename(newPath)
107
- let content = entry.content
108
- if (Node.isBinary(entry) && typeof content === 'string') {
109
- content = Crypto.bs64.decode(content)
125
+ let entry = (
126
+ await cat.cat({
127
+ path: originalPath,
128
+ version: options.version,
129
+ unformatted: true,
130
+ })
131
+ )[0];
132
+ let dir = await lpwd.lpwd();
133
+ let newPath = path.join(
134
+ dir,
135
+ path.basename(p) +
136
+ (options.encrypt ? ".secrez" + (Node.isBinary(entry) ? "b" : "") : "")
137
+ );
138
+ let name = await efs.getVersionedBasename(newPath);
139
+ let content = entry.content;
140
+ if (Node.isBinary(entry) && typeof content === "string") {
141
+ content = Crypto.bs64.decode(content);
110
142
  }
111
- if (options.encrypt) {
112
- const myPublicKey = this.secrez.getPublicKey()
143
+ if (options.keystore) {
144
+ let card;
145
+ try {
146
+ card = yamlParse(content);
147
+ } catch (e) {
148
+ throw new Error("The entry is not a valid card");
149
+ }
150
+ let pks = [];
151
+ for (let k in card) {
152
+ if (/private_key/.test(k)) {
153
+ pks.push(k);
154
+ }
155
+ }
156
+ if (!pks.length) {
157
+ throw new Error("The entry does not contain any private key");
158
+ }
159
+ let privateKey = card[pks[0]];
160
+ if (pks.length > 1) {
161
+ let pk = await this.useInput({
162
+ type: "list",
163
+ message: "Which private key do you want to export?",
164
+ choices: pks,
165
+ });
166
+ privateKey = card[pk];
167
+ }
168
+ let pwd =
169
+ options.password ||
170
+ (await this.useInput({
171
+ type: "password",
172
+ message: "Type the password to encrypt the keystore file",
173
+ }));
174
+ if (!pwd) {
175
+ throw new Error("Operation canceled");
176
+ }
177
+ content = await encryptPrivateKeyAsKeystoreJson(privateKey, pwd);
178
+ name = name.replace(/\.[^.]+$/, ".keystore.json");
179
+ } else if (options.encrypt) {
180
+ const myPublicKey = this.secrez.getPublicKey();
113
181
  if (options.publicKeys) {
114
- if (options.includeMe && options.publicKeys.indexOf(myPublicKey) === -1) {
115
- options.publicKeys.push(myPublicKey)
182
+ if (
183
+ options.includeMe &&
184
+ options.publicKeys.indexOf(myPublicKey) === -1
185
+ ) {
186
+ options.publicKeys.push(myPublicKey);
116
187
  }
117
188
  } else if (options.contacts) {
118
- options.publicKeys = await this.getContactsPublicKeys(options)
189
+ options.publicKeys = await this.getContactsPublicKeys(options);
119
190
  if (options.includeMe) {
120
- options.publicKeys.push(myPublicKey)
191
+ options.publicKeys.push(myPublicKey);
121
192
  }
122
193
  } else if (options.includeMe) {
123
- options.publicKeys = [myPublicKey]
194
+ options.publicKeys = [myPublicKey];
124
195
  } else {
125
- let pwd = options.password || await this.useInput({
126
- type: 'password',
127
- message: 'Type the password'
128
- })
196
+ let pwd =
197
+ options.password ||
198
+ (await this.useInput({
199
+ type: "password",
200
+ message: "Type the password",
201
+ }));
129
202
  if (!pwd) {
130
- throw new Error('Operation canceled')
203
+ throw new Error("Operation canceled");
131
204
  }
132
- let pwd2 = options.password || await this.useInput({
133
- type: 'password',
134
- message: 'Retype it'
135
- })
205
+ let pwd2 =
206
+ options.password ||
207
+ (await this.useInput({
208
+ type: "password",
209
+ message: "Retype it",
210
+ }));
136
211
  if (!pwd2) {
137
- throw new Error('Operation canceled')
212
+ throw new Error("Operation canceled");
138
213
  }
139
214
  if (pwd !== pwd2) {
140
- throw new Error('The two password do not match')
215
+ throw new Error("The two password do not match");
141
216
  }
142
- options.password = pwd
217
+ options.password = pwd;
143
218
  }
144
- content = fileCipher.encryptFile(content, options).join(',')
219
+ content = fileCipher.encryptFile(content, options).join(",");
145
220
  }
146
- let fn = path.join(dir, name)
147
- await fs.writeFile(fn, content)
221
+ let fn = path.join(dir, name);
222
+ await fs.writeFile(fn, content);
148
223
  if (options.duration) {
149
- this.deleteFromDisk(fn, options.duration)
224
+ // we do not wait for the deletion
225
+ this.deleteFromDisk(fn, options.duration).then();
150
226
  }
151
- return name
227
+ return name;
152
228
  } else {
153
- throw new Error('Cannot export a folder')
229
+ throw new Error("Cannot export a folder");
154
230
  }
155
231
  }
156
232
 
157
233
  async getContactsPublicKeys(options) {
158
- let contacts = await this.prompt.commands.contacts.contacts({list: true, asIs: true})
159
- let publicKeys = []
234
+ let contacts = await this.prompt.commands.contacts.contacts({
235
+ list: true,
236
+ asIs: true,
237
+ });
238
+ let publicKeys = [];
160
239
  for (let contact of contacts) {
161
240
  if (options.contacts.indexOf(contact[0]) !== -1) {
162
- publicKeys.push(contact[1].publicKey)
241
+ publicKeys.push(contact[1].publicKey);
163
242
  }
164
243
  }
165
- return publicKeys
244
+ return publicKeys;
166
245
  }
167
246
 
168
247
  async deleteFromDisk(fn, duration) {
169
- await sleep(1000 * duration)
248
+ await sleep(1000 * duration);
170
249
  if (await fs.pathExists(fn)) {
171
- fs.unlink(fn)
250
+ fs.unlink(fn);
172
251
  }
173
252
  }
174
253
 
175
254
  async exec(options = {}) {
176
255
  if (options.help) {
177
- return this.showHelp()
256
+ return this.showHelp();
178
257
  }
179
258
  try {
180
- this.validate(options)
181
- let name = await this.export(options)
182
- this.Logger.grey('Exported file:')
183
- this.Logger.reset(name)
184
- if (options.encrypt && !options.password && !options.includeMe && !this.alerted) {
185
- this.Logger.yellow(chalk.red('One time alert: ') + 'Only the users for which you encrypted the data can decrypt it; not even you can decrypt the exported data. Be careful!')
186
- this.alerted = true
259
+ this.validate(options);
260
+ let name = await this.export(options);
261
+ this.Logger.grey("Exported file:");
262
+ this.Logger.reset(name);
263
+ if (
264
+ options.encrypt &&
265
+ !options.password &&
266
+ !options.includeMe &&
267
+ !this.alerted
268
+ ) {
269
+ this.Logger.yellow(
270
+ chalk.red("One time alert: ") +
271
+ "Only the users for which you encrypted the data can decrypt it; not even you can decrypt the exported data. Be careful!"
272
+ );
273
+ this.alerted = true;
187
274
  }
188
275
  } catch (e) {
189
- this.Logger.red(e.message)
276
+ this.Logger.red(e.message);
190
277
  }
191
- await this.prompt.run()
278
+ await this.prompt.run();
192
279
  }
193
280
  }
194
281
 
195
- module.exports = Export
196
-
197
-
282
+ module.exports = Export;