secrez 1.1.6 → 2.0.0

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.
@@ -1,8 +1,6 @@
1
1
  const Crypto = require("@secrez/crypto");
2
- const { utils: hubUtils } = require("@secrez/hub");
3
2
  const chalk = require("chalk");
4
3
  const ContactManager = require("../utils/ContactManager");
5
- const superagent = require("superagent");
6
4
 
7
5
  class Contacts extends require("../Command") {
8
6
  setHelpAndCompletion() {
@@ -57,10 +55,10 @@ class Contacts extends require("../Command") {
57
55
  examples: [
58
56
  [
59
57
  "contacts -a pan",
60
- "adds a new trusted contact pan, asking for his public key or hub url",
58
+ "adds a new trusted contact pan, asking for his public key",
61
59
  ],
62
- ["contacts -u pan", "updates the hub url"],
63
- ["contacts -s pan", "returns pan's public key and url"],
60
+ ["contacts -u pan", "updates a contact"],
61
+ ["contacts -s pan", "returns pan's public key"],
64
62
  ["contacts -d ema", "deletes ema's data"],
65
63
  ["contacts -r ema joe", "renames ema"],
66
64
  ["contacts", "listed all trusted contacts"],
@@ -68,20 +66,6 @@ class Contacts extends require("../Command") {
68
66
  };
69
67
  }
70
68
 
71
- async getPublicKeyFromUrl(url) {
72
- try {
73
- url = new URL(url);
74
- let id = hubUtils.getClientIdFromHostname(url.hostname);
75
- let apiurl = url.protocol + "//" + url.host.split(id + ".")[1];
76
- let res = await superagent
77
- .get(`${apiurl}/api/v1/publickey/${id}`)
78
- .set("Accept", "application/json");
79
- return res.body.publickey;
80
- } catch (e) {
81
- throw new Error("Inactive/wrong url");
82
- }
83
- }
84
-
85
69
  async createContact(options) {
86
70
  const { name } = options;
87
71
  if (options.update) {
@@ -90,7 +74,6 @@ class Contacts extends require("../Command") {
90
74
  await this.contactManager.create({
91
75
  name,
92
76
  publicKey: options.publicKey,
93
- url: options.url,
94
77
  });
95
78
  }
96
79
 
@@ -101,57 +84,27 @@ class Contacts extends require("../Command") {
101
84
  throw new Error(`A contact named "${name}" already exists`);
102
85
  }
103
86
  let publicKey;
104
- let url;
105
87
  if (process.env.NODE_ENV === "test") {
106
88
  publicKey = options.publicKey;
107
- url = options.url;
108
89
  } else {
109
- let choice = await this.useSelect({
110
- message: "Chose method",
111
- choices: ["Public key", "Url on hub"],
112
- });
113
- if (!choice) {
114
- throw new Error("Operation canceled");
115
- }
116
- if (choice === "Url on hub") {
117
- url = await this.useInput(
118
- Object.assign(options, {
119
- message: `Paste ${name}'s url on hub`,
120
- })
121
- );
122
- if (!url) {
123
- throw new Error("Operation canceled");
124
- }
125
- try {
126
- publicKey = await this.getPublicKeyFromUrl(url);
127
- } catch (e) {}
128
- } else {
129
- publicKey = await this.useInput(
130
- Object.assign(options, {
131
- message: `Paste ${name}'s public key`,
132
- })
133
- );
134
- }
90
+ publicKey = await this.useInput(
91
+ Object.assign(options, {
92
+ message: `Paste ${name}'s public key`,
93
+ })
94
+ );
135
95
  if (!publicKey) {
136
- throw new Error(
137
- choice === "Url on hub"
138
- ? "Client not found on hub"
139
- : "Operation canceled"
140
- );
96
+ throw new Error("Operation canceled");
141
97
  }
142
98
  }
143
99
  if (!Crypto.isValidSecrezPublicKey(publicKey)) {
144
100
  throw new Error("The public key is not a valid one");
145
101
  }
146
- if (url && !hubUtils.isValidUrl(url)) {
147
- throw new Error("The url does not look valid");
148
- }
149
- this.checkIfAlreadyExists(name, publicKey, url);
150
- await this.createContact(Object.assign(options, { publicKey, url }));
102
+ this.checkIfAlreadyExists(name, publicKey);
103
+ await this.createContact(Object.assign(options, { publicKey }));
151
104
  return `The contact "${name}" has been added to your trusted contacts`;
152
105
  }
153
106
 
154
- checkIfAlreadyExists(name, publicKey, url) {
107
+ checkIfAlreadyExists(name, publicKey, updating = false) {
155
108
  let allContacts = this.contactManager.get();
156
109
  for (let contact in allContacts) {
157
110
  let content = JSON.parse(allContacts[contact].content);
@@ -160,17 +113,11 @@ class Contacts extends require("../Command") {
160
113
  throw new Error(
161
114
  `The contact "${contact}" is already associated to this public key`
162
115
  );
163
- } else if (url && content.url === url) {
164
- throw new Error(
165
- `The contact "${contact}" is already associated to this url`
166
- );
167
- }
168
- } else {
169
- if (publicKey && content.publicKey !== publicKey) {
170
- throw new Error(
171
- `"${contact}" is associated to a different public key. Verify your contact, please`
172
- );
173
116
  }
117
+ } else if (!updating && content.publicKey !== publicKey) {
118
+ throw new Error(
119
+ `"${contact}" is associated to a different public key. Verify your contact, please`
120
+ );
174
121
  }
175
122
  }
176
123
  }
@@ -182,48 +129,26 @@ class Contacts extends require("../Command") {
182
129
  throw new Error("Contact not found");
183
130
  }
184
131
  let publicKey;
185
- let url;
186
132
  if (process.env.NODE_ENV === "test") {
187
133
  publicKey = options.publicKey;
188
- url = options.url;
189
134
  } else {
190
- let choice = await this.useSelect({
191
- message: "Chose method",
192
- choices: ["Public key", "Url on hub"],
193
- });
194
- if (choice === "Url on hub") {
195
- url = await this.useInput(
196
- Object.assign(options, {
197
- message: `Paste ${name}'s url on hub`,
198
- })
199
- );
200
- if (!url) {
201
- throw new Error("Operation canceled");
202
- }
203
- try {
204
- publicKey = await this.getPublicKeyFromUrl(url);
205
- } catch (e) {}
206
- } else {
207
- publicKey = await this.useInput(
208
- Object.assign(options, {
209
- message: `Paste ${name}'s public key`,
210
- })
211
- );
212
- }
135
+ publicKey = await this.useInput(
136
+ Object.assign(options, {
137
+ message: `Paste ${name}'s public key`,
138
+ })
139
+ );
213
140
  if (!publicKey) {
214
- throw new Error(
215
- choice === "Url on hub" ? "Url not active" : "Operation canceled"
216
- );
141
+ throw new Error("Operation canceled");
217
142
  }
218
143
  }
219
144
  if (!publicKey) {
220
145
  publicKey = JSON.parse(existingDataIfSo.content).publicKey;
221
146
  }
222
- this.checkIfAlreadyExists(name, publicKey, url);
147
+ this.checkIfAlreadyExists(name, publicKey, true);
223
148
  if (existingDataIfSo) {
224
149
  await this.contactManager.remove(name);
225
150
  }
226
- await this.createContact(Object.assign(options, { publicKey, url }));
151
+ await this.createContact(Object.assign(options, { publicKey }));
227
152
  return `The contact "${name}" has been updated`;
228
153
  }
229
154
 
@@ -277,9 +202,6 @@ class Contacts extends require("../Command") {
277
202
  chalk.grey("public key: "),
278
203
  l[1].publicKey,
279
204
  ];
280
- if (l[1].url) {
281
- result.push("\n", chalk.grey("url: "), l[1].url);
282
- }
283
205
  return result.join("");
284
206
  }
285
207
 
@@ -0,0 +1,149 @@
1
+ const QRCode = require("qrcode");
2
+ const { yamlParse, isYaml } = require("@secrez/utils");
3
+ const { Node } = require("@secrez/fs");
4
+ const _ = require("lodash");
5
+
6
+ class Show extends require("../Command") {
7
+ setHelpAndCompletion() {
8
+ this.cliConfig.completion.show = {
9
+ _func: this.selfCompletion(this),
10
+ _self: this,
11
+ };
12
+ this.cliConfig.completion.help.show = true;
13
+ this.optionDefinitions = [
14
+ {
15
+ name: "help",
16
+ alias: "h",
17
+ type: Boolean,
18
+ },
19
+ {
20
+ name: "path",
21
+ completionType: "file",
22
+ alias: "p",
23
+ defaultOption: true,
24
+ type: String,
25
+ },
26
+ {
27
+ name: "version",
28
+ alias: "v",
29
+ type: Boolean,
30
+ },
31
+ {
32
+ name: "qr-code",
33
+ alias: "q",
34
+ type: Boolean,
35
+ },
36
+ {
37
+ name: "field",
38
+ alias: "f",
39
+ type: String,
40
+ },
41
+ ];
42
+ }
43
+
44
+ help() {
45
+ return {
46
+ description: ["Show a card field as a QR code."],
47
+ examples: [
48
+ [
49
+ "show -q wallet.yml -f password",
50
+ "shows the field 'password' of the card 'wallet.yml' as a QR code",
51
+ ],
52
+ [
53
+ "show wallet.yml -f password",
54
+ "shows the field 'password' of the card 'wallet.yml'",
55
+ ],
56
+ [
57
+ "show ethKeys.yaml -v 8uW3",
58
+ "asks you to select a field from the version 8uW3 of the file",
59
+ ],
60
+ ],
61
+ };
62
+ }
63
+
64
+ async generateQrCode(content) {
65
+ return new Promise((resolve, reject) => {
66
+ QRCode.toString(content, { type: "terminal" }, (err, qrcode) => {
67
+ if (err) reject(err);
68
+ else resolve(qrcode);
69
+ });
70
+ });
71
+ }
72
+
73
+ async show(options) {
74
+ let cat = this.prompt.commands.cat;
75
+ let currentIndex = this.internalFs.treeIndex;
76
+ let data = await this.internalFs.getTreeIndexAndPath(options.path);
77
+ /* istanbul ignore if */
78
+ if (currentIndex !== data.index) {
79
+ await this.internalFs.mountTree(data.index, true);
80
+ }
81
+ options.path = data.path;
82
+ let tree = data.tree;
83
+ let p = tree.getNormalizedPath(options.path);
84
+ let file = tree.root.getChildFromPath(p);
85
+ if (Node.isFile(file)) {
86
+ let entry = (
87
+ await cat.cat({
88
+ path: p,
89
+ version: options.version ? [options.version] : undefined,
90
+ unformatted: true,
91
+ })
92
+ )[0];
93
+ if (Node.isText(entry)) {
94
+ let { name, content } = entry;
95
+ if (isYaml(p)) {
96
+ let parsed;
97
+ try {
98
+ parsed = yamlParse(content);
99
+ } catch (e) {
100
+ throw new Error("The yml is malformed.");
101
+ }
102
+ if (options.field) {
103
+ if (parsed[options.field]) {
104
+ content = parsed[options.field];
105
+ } else {
106
+ throw new Error(`Field ${options.field} not found`);
107
+ }
108
+ } else {
109
+ let field = await this.useInput({
110
+ type: "list",
111
+ message: "Which field do you want to show?",
112
+ choices: Object.keys(parsed),
113
+ });
114
+ content = parsed[field];
115
+ }
116
+ if (options.qrCode) {
117
+ return this.generateQrCode(content);
118
+ } else {
119
+ return content;
120
+ }
121
+ }
122
+ } else {
123
+ throw new Error("File is not a card.");
124
+ }
125
+ } else {
126
+ throw new Error("Cannot show a folder");
127
+ }
128
+ }
129
+
130
+ async exec(options = {}) {
131
+ if (options.help) {
132
+ return this.showHelp();
133
+ }
134
+ try {
135
+ this.validate(options, {
136
+ path: true,
137
+ });
138
+ const content = await this.show(options);
139
+ if (content) {
140
+ this.Logger.reset(content);
141
+ }
142
+ } catch (e) {
143
+ this.Logger.red(e.message);
144
+ }
145
+ await this.prompt.run();
146
+ }
147
+ }
148
+
149
+ module.exports = Show;
@@ -1,6 +1,4 @@
1
1
  const chalk = require("chalk");
2
- const { ConfigUtils } = require("@secrez/core");
3
- const clipboardy = require("clipboardy");
4
2
 
5
3
  class Whoami extends require("../Command") {
6
4
  setHelpAndCompletion() {
@@ -20,12 +18,12 @@ class Whoami extends require("../Command") {
20
18
 
21
19
  help() {
22
20
  return {
23
- description: ["Show data that other users need to chat with you"],
21
+ description: ["Show your Secrez public key"],
24
22
  examples: ["whoami"],
25
23
  };
26
24
  }
27
25
 
28
- async customCompletion(options, originalLine, defaultOption) {
26
+ async customCompletion() {
29
27
  return [];
30
28
  }
31
29
 
@@ -33,24 +31,10 @@ class Whoami extends require("../Command") {
33
31
  let result = {
34
32
  publicKey: this.secrez.getPublicKey(),
35
33
  };
36
- const env = (options.env = await ConfigUtils.getEnv(this.secrez.config));
37
- if (env.courier) {
38
- await this.prompt.commands.courier.preInit(options);
39
- if (options.ready) {
40
- result.url = env.courier.tunnel.url;
41
- }
42
- }
43
34
  if (options.asIs) {
44
35
  return result;
45
36
  }
46
37
  this.Logger.reset(chalk.grey("Public key: ") + result.publicKey);
47
- if (result.url) {
48
- this.Logger.reset(chalk.grey("Hub url: ") + result.url);
49
- await clipboardy.write(result.url);
50
- this.Logger.grey(
51
- "For your convenience, the url has been copied to the clipboard."
52
- );
53
- }
54
38
  }
55
39
 
56
40
  async exec(options = {}) {
@@ -22,7 +22,6 @@ class ContactManager {
22
22
  value: options.name,
23
23
  content: JSON.stringify({
24
24
  publicKey: options.publicKey,
25
- url: options.url,
26
25
  }),
27
26
  });
28
27
  }
@@ -38,12 +37,13 @@ class ContactManager {
38
37
  }
39
38
  }
40
39
 
41
- async rename(existentName, contact) {
40
+ async rename(existentName, name) {
42
41
  let old = this.get(existentName);
42
+ let { publicKey } = JSON.parse(old.content);
43
43
  if (await this.remove(existentName)) {
44
44
  return await this.create({
45
- name: contact,
46
- content: old.content,
45
+ name,
46
+ publicKey,
47
47
  });
48
48
  }
49
49
  }
@@ -1,148 +0,0 @@
1
- const path = require("path");
2
- const chalk = require("chalk");
3
- const { ConfigUtils } = require("@secrez/core");
4
- const ChatPrompt = require("../prompts/ChatPrompt");
5
-
6
- class Chat extends require("../Command") {
7
- setHelpAndCompletion() {
8
- this.cliConfig.completion.chat = {
9
- _func: this.selfCompletion(this),
10
- _self: this,
11
- };
12
- this.cliConfig.completion.help.chat = true;
13
- this.optionDefinitions = [
14
- {
15
- name: "help",
16
- alias: "h",
17
- type: Boolean,
18
- },
19
- ];
20
- }
21
-
22
- help() {
23
- return {
24
- description: ["Enters the Secrez chat"],
25
- examples: ["chat"],
26
- };
27
- }
28
-
29
- async uploadUsersPublicKeysToCourier(options) {
30
- const { port, caCrt } = options.env.courier;
31
- let contacts = await this.prompt.commands.contacts.contacts({
32
- list: true,
33
- asIs: true,
34
- });
35
- this.contactsByPublicKey = {};
36
- for (let contact of contacts) {
37
- this.contactsByPublicKey[contact[1].publicKey] = contact[0];
38
- await this.callCourier(
39
- {
40
- action: {
41
- name: "add",
42
- publicKey: contact[1].publicKey,
43
- url: contact[1].url,
44
- },
45
- },
46
- port,
47
- caCrt,
48
- "/admin"
49
- );
50
- }
51
- }
52
-
53
- async readHistoryMessages(options = {}) {
54
- /* istanbul ignore if */
55
- if (!options.asIs) {
56
- this.chatPrompt.skip = true;
57
- }
58
- const { minTimestamp, maxTimestamp, from, to } = options;
59
- /* istanbul ignore if */
60
- if (!options.asIs) {
61
- this.Logger.bold(
62
- from || to
63
- ? `Messages${from ? ` from ${from}` : ""}${to ? ` to ${to}` : ""}:`
64
- : "All message history:"
65
- );
66
- }
67
- let newMessages = await this.prompt.commands.courier.getSomeMessages({
68
- payload: {
69
- minTimestamp,
70
- maxTimestamp,
71
- from: this.room[0].publicKey,
72
- limit: 1000,
73
- },
74
- });
75
- /* istanbul ignore if */
76
- if (!options.asIs) {
77
- let len = newMessages.length;
78
- if (len) {
79
- this.chatPrompt.onMessages(newMessages, {
80
- fromHistory: true,
81
- verbose: options.verbose,
82
- lastLine: options.asIs
83
- ? undefined
84
- : chalk.grey(`${len} message${len > 1 ? "s" : ""} found.`),
85
- });
86
- } else {
87
- this.Logger.yellow("None found");
88
- }
89
- this.chatPrompt.skip = false;
90
- } else {
91
- return newMessages;
92
- }
93
- }
94
-
95
- async chat(options) {
96
- const env = (options.env = await ConfigUtils.getEnv(this.secrez.config));
97
- if (env.courier) {
98
- this.courier = await this.prompt.commands.courier;
99
- await this.courier.preInit(options);
100
- if (options.ready) {
101
- await this.uploadUsersPublicKeysToCourier(options);
102
- if (process.env.NODE_ENV === "test") {
103
- this.chatPrompt = options.chatPrompt;
104
- } else {
105
- this.chatPrompt = new ChatPrompt();
106
- }
107
- await this.chatPrompt.init({
108
- historyPath: path.join(
109
- this.secrez.config.localDataPath,
110
- "chatHistory"
111
- ),
112
- environment: this,
113
- secrez: this.secrez,
114
- });
115
- await this.chatPrompt.run(options);
116
- } else {
117
- throw new Error("The configured courier is not responding.");
118
- }
119
- } else {
120
- this.Logger.grey(`Chat requires a courier listening locally.
121
- If you haven't yet, in another terminal install @secrez/courier as
122
-
123
- npm i -g @secrez/courier
124
-
125
- and launch it as
126
-
127
- secrez-courier
128
-
129
- It will show the port where it is listening to. Copy it and come back to Secrez. Then run "courier" to configure the connection w/ the courier.`);
130
- throw new Error("Courier not found.");
131
- }
132
- }
133
-
134
- async exec(options = {}) {
135
- if (options.help) {
136
- return this.showHelp();
137
- }
138
- try {
139
- await this.chat(options);
140
- } catch (e) {
141
- // console.log(e)
142
- this.Logger.red(e.message);
143
- }
144
- await this.prompt.run();
145
- }
146
- }
147
-
148
- module.exports = Chat;