secrez 1.1.1 → 1.1.2
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.
- package/README.md +414 -291
- package/bin/secrez.js +50 -47
- package/coverage.report +63 -305
- package/package.json +10 -12
- package/src/Command.js +78 -57
- package/src/PreCommand.js +74 -70
- package/src/Welcome.js +144 -134
- package/src/cliConfig.js +14 -14
- package/src/commands/Alias.js +123 -100
- package/src/commands/Bash.js +10 -12
- package/src/commands/Cat.js +117 -107
- package/src/commands/Cd.js +39 -42
- package/src/commands/Chat.js +75 -63
- package/src/commands/Conf.js +123 -99
- package/src/commands/Contacts.js +189 -171
- package/src/commands/Copy.js +132 -113
- package/src/commands/Courier.js +123 -105
- package/src/commands/Ds.js +88 -76
- package/src/commands/Edit.js +122 -103
- package/src/commands/Export.js +153 -114
- package/src/commands/Find.js +115 -110
- package/src/commands/Help.js +20 -23
- package/src/commands/Import.js +296 -225
- package/src/commands/Lcat.js +36 -39
- package/src/commands/Lcd.js +38 -39
- package/src/commands/Lls.js +58 -55
- package/src/commands/Lpwd.js +20 -24
- package/src/commands/Ls.js +107 -97
- package/src/commands/Mkdir.js +35 -38
- package/src/commands/Mv.js +147 -114
- package/src/commands/Paste.js +68 -65
- package/src/commands/Pwd.js +18 -23
- package/src/commands/Quit.js +22 -24
- package/src/commands/Rm.js +78 -70
- package/src/commands/Shell.js +31 -32
- package/src/commands/Ssh.js +77 -63
- package/src/commands/Tag.js +133 -112
- package/src/commands/Totp.js +166 -136
- package/src/commands/Touch.js +169 -56
- package/src/commands/Use.js +44 -41
- package/src/commands/Ver.js +16 -18
- package/src/commands/Whoami.js +34 -37
- package/src/commands/chat/Contacts.js +41 -44
- package/src/commands/chat/Help.js +20 -23
- package/src/commands/chat/Join.js +59 -55
- package/src/commands/chat/Leave.js +16 -22
- package/src/commands/chat/Quit.js +19 -24
- package/src/commands/chat/Send.js +58 -57
- package/src/commands/chat/Show.js +60 -51
- package/src/commands/chat/Whoami.js +18 -22
- package/src/commands/index.js +20 -22
- package/src/index.js +3 -3
- package/src/prompts/ChatPrompt.js +87 -82
- package/src/prompts/ChatPromptMock.js +11 -17
- package/src/prompts/CommandPrompt.js +146 -138
- package/src/prompts/Completion.js +64 -69
- package/src/prompts/MainPrompt.js +84 -77
- package/src/prompts/MainPromptMock.js +19 -30
- package/src/prompts/MultiEditorPrompt.js +21 -22
- package/src/prompts/SigintManager.js +21 -24
- package/src/utils/AliasManager.js +16 -18
- package/src/utils/ContactManager.js +15 -17
- package/src/utils/Fido2Client.js +59 -49
- package/src/utils/HelpProto.js +130 -117
- package/src/utils/Logger.js +48 -50
- package/.eslintignore +0 -0
- package/.eslintrc +0 -33
- package/.jshintrc +0 -3
package/src/commands/Edit.js
CHANGED
@@ -1,199 +1,218 @@
|
|
1
1
|
// Next line is to avoid that npm-check-unused reports it
|
2
|
-
require(
|
2
|
+
require("tiny-cli-editor");
|
3
3
|
//
|
4
4
|
|
5
|
-
const _ = require(
|
6
|
-
const path = require(
|
7
|
-
const fs = require(
|
8
|
-
const {Entry} = require(
|
9
|
-
const {
|
10
|
-
|
11
|
-
|
5
|
+
const _ = require("lodash");
|
6
|
+
const path = require("path");
|
7
|
+
const fs = require("fs-extra");
|
8
|
+
const { Entry } = require("@secrez/core");
|
9
|
+
const {
|
10
|
+
isYaml,
|
11
|
+
yamlParse,
|
12
|
+
yamlStringify,
|
13
|
+
execAsync,
|
14
|
+
} = require("@secrez/utils");
|
12
15
|
|
16
|
+
class Edit extends require("../Command") {
|
13
17
|
setHelpAndCompletion() {
|
14
18
|
this.cliConfig.completion.edit = {
|
15
19
|
_func: this.selfCompletion(this),
|
16
|
-
_self: this
|
17
|
-
}
|
18
|
-
this.cliConfig.completion.help.edit = true
|
20
|
+
_self: this,
|
21
|
+
};
|
22
|
+
this.cliConfig.completion.help.edit = true;
|
19
23
|
this.optionDefinitions = [
|
20
24
|
{
|
21
|
-
name:
|
22
|
-
alias:
|
23
|
-
type: Boolean
|
25
|
+
name: "help",
|
26
|
+
alias: "h",
|
27
|
+
type: Boolean,
|
24
28
|
},
|
25
29
|
{
|
26
|
-
name:
|
27
|
-
completionType:
|
28
|
-
alias:
|
30
|
+
name: "path",
|
31
|
+
completionType: "file",
|
32
|
+
alias: "p",
|
29
33
|
defaultOption: true,
|
30
|
-
type: String
|
34
|
+
type: String,
|
31
35
|
},
|
32
36
|
{
|
33
|
-
name:
|
34
|
-
alias:
|
35
|
-
type: String
|
37
|
+
name: "editor",
|
38
|
+
alias: "e",
|
39
|
+
type: String,
|
36
40
|
},
|
37
41
|
{
|
38
|
-
name:
|
39
|
-
alias:
|
40
|
-
type: Boolean
|
42
|
+
name: "internal",
|
43
|
+
alias: "i",
|
44
|
+
type: Boolean,
|
41
45
|
},
|
42
46
|
{
|
43
|
-
name:
|
44
|
-
alias:
|
45
|
-
type: String
|
47
|
+
name: "field",
|
48
|
+
alias: "f",
|
49
|
+
type: String,
|
46
50
|
},
|
47
51
|
{
|
48
|
-
name:
|
49
|
-
alias:
|
52
|
+
name: "unformatted",
|
53
|
+
alias: "u",
|
50
54
|
type: Boolean,
|
51
|
-
hint:
|
52
|
-
}
|
53
|
-
]
|
55
|
+
hint: "If a Yaml file, it edits it without parsing the file",
|
56
|
+
},
|
57
|
+
];
|
54
58
|
}
|
55
59
|
|
56
60
|
help() {
|
57
61
|
return {
|
58
62
|
description: [
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
"Edits a file containing a secret.",
|
64
|
+
"If no default editor is installed, you can use the minimalistic internal editor.",
|
65
|
+
"It supports only two commands:",
|
66
|
+
"" + " Ctrl-c to cancel",
|
67
|
+
" Ctrl-d to save",
|
68
|
+
"WARNING: Do not quit forcely because a temp file can remain on disk, unencrypted. If for any reason you do it, launch Secrez again because at start it empties the temp folder.",
|
65
69
|
],
|
66
70
|
examples: [
|
67
|
-
[
|
68
|
-
[
|
69
|
-
[
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
["edit ../coins/ether2-pwd", "uses the OS default editor"],
|
72
|
+
["edit ../bitcoin/seed -i", "uses the minimalistic internal editor"],
|
73
|
+
[
|
74
|
+
"edit ../bitcoin/seed -e nano",
|
75
|
+
"choses the editor, in this case nano",
|
76
|
+
],
|
77
|
+
["edit ../bitcoin/seed -e vim", "uses vim"],
|
78
|
+
[
|
79
|
+
"edit gmail.yml -f password",
|
80
|
+
"edits only the field password of the yaml file. If the field does not exist, a new field is added",
|
81
|
+
],
|
82
|
+
["edit damaged.yaml -u", "edits damaged.yaml without parsing it"],
|
83
|
+
],
|
84
|
+
};
|
75
85
|
}
|
76
86
|
|
77
87
|
async edit(options) {
|
78
|
-
let file = options.path
|
88
|
+
let file = options.path;
|
79
89
|
if (/:/.test(file)) {
|
80
90
|
// TODO Fix this
|
81
|
-
throw new Error(
|
91
|
+
throw new Error(
|
92
|
+
"Edit works only on the current dataset. Remove the dataset from the path, please"
|
93
|
+
);
|
82
94
|
}
|
83
|
-
let sanitizedPath = Entry.sanitizePath(options.path)
|
95
|
+
let sanitizedPath = Entry.sanitizePath(options.path);
|
84
96
|
if (sanitizedPath !== options.path) {
|
85
|
-
throw new Error(
|
97
|
+
throw new Error("A filename cannot contain \\/><|:&?*^$ chars.");
|
86
98
|
}
|
87
|
-
let exists = false
|
88
|
-
let fileData
|
99
|
+
let exists = false;
|
100
|
+
let fileData;
|
89
101
|
try {
|
90
|
-
fileData = await this.prompt.commands.cat.cat({path: file}, true)
|
91
|
-
exists = true
|
102
|
+
fileData = await this.prompt.commands.cat.cat({ path: file }, true);
|
103
|
+
exists = true;
|
92
104
|
} catch (e) {
|
93
105
|
if (options.field) {
|
94
|
-
throw new Error(
|
106
|
+
throw new Error("Field can be specified only for existent files");
|
95
107
|
}
|
96
|
-
fileData = [{content:
|
108
|
+
fileData = [{ content: "" }];
|
97
109
|
}
|
98
110
|
|
99
|
-
let fields = {}
|
111
|
+
let fields = {};
|
100
112
|
if (exists && !options.unformatted && isYaml(file)) {
|
101
|
-
fields = fileData[0].content ? yamlParse(fileData[0].content) : {}
|
102
|
-
if (typeof fields ===
|
103
|
-
options.choices = Object.keys(fields)
|
113
|
+
fields = fileData[0].content ? yamlParse(fileData[0].content) : {};
|
114
|
+
if (typeof fields === "object") {
|
115
|
+
options.choices = Object.keys(fields);
|
104
116
|
if (options.choices.length && !options.field) {
|
105
|
-
options.message =
|
106
|
-
options.field = await this.useSelect(options)
|
117
|
+
options.message = "Select the field to edit";
|
118
|
+
options.field = await this.useSelect(options);
|
107
119
|
if (!options.field) {
|
108
|
-
this.Logger.reset(
|
109
|
-
return
|
120
|
+
this.Logger.reset("Changes aborted or file not changed");
|
121
|
+
return;
|
110
122
|
}
|
111
123
|
}
|
112
124
|
} else {
|
113
|
-
delete options.field
|
125
|
+
delete options.field;
|
114
126
|
}
|
115
127
|
} else if (!isYaml(file)) {
|
116
|
-
delete options.field
|
128
|
+
delete options.field;
|
117
129
|
}
|
118
|
-
let content = options.field
|
119
|
-
|
130
|
+
let content = options.field
|
131
|
+
? fields[options.field] || ""
|
132
|
+
: fileData[0].content;
|
133
|
+
let newContent = await this.useEditor(Object.assign(options, { content }));
|
120
134
|
|
121
135
|
if (newContent && newContent !== content) {
|
122
136
|
if (exists) {
|
123
|
-
let node = this.internalFs.tree.workingNode.getChildFromPath(file)
|
124
|
-
let entry = node.getEntry()
|
137
|
+
let node = this.internalFs.tree.workingNode.getChildFromPath(file);
|
138
|
+
let entry = node.getEntry();
|
125
139
|
if (options.field) {
|
126
|
-
fields[options.field] = _.trim(newContent)
|
127
|
-
entry.content = yamlStringify(fields)
|
140
|
+
fields[options.field] = _.trim(newContent);
|
141
|
+
entry.content = yamlStringify(fields);
|
128
142
|
} else {
|
129
|
-
entry.content = newContent
|
143
|
+
entry.content = newContent;
|
130
144
|
}
|
131
|
-
await this.internalFs.tree.update(node, entry)
|
145
|
+
await this.internalFs.tree.update(node, entry);
|
132
146
|
} else {
|
133
147
|
await this.prompt.commands.touch.touch({
|
134
148
|
path: file,
|
135
|
-
|
136
|
-
})
|
149
|
+
content: newContent,
|
150
|
+
});
|
137
151
|
}
|
138
|
-
this.Logger.reset(
|
152
|
+
this.Logger.reset("File saved.");
|
139
153
|
} else {
|
140
|
-
this.Logger.reset(
|
154
|
+
this.Logger.reset("Changes aborted or file not changed");
|
141
155
|
}
|
142
156
|
}
|
143
157
|
|
144
158
|
getTinyCliEditorBinPath() {
|
145
159
|
if (!this.editorBinPath) {
|
146
|
-
|
147
|
-
|
160
|
+
let bin = path.resolve(
|
161
|
+
__dirname,
|
162
|
+
"../../node_modules/tiny-cli-editor/bin.js"
|
163
|
+
);
|
148
164
|
if (!fs.existsSync(bin)) {
|
149
|
-
bin = path.resolve(
|
165
|
+
bin = path.resolve(
|
166
|
+
__dirname,
|
167
|
+
"../../../../node_modules/tiny-cli-editor/bin.js"
|
168
|
+
);
|
150
169
|
}
|
151
170
|
if (!fs.existsSync(bin)) {
|
152
|
-
throw new Error(
|
171
|
+
throw new Error("Default editor not found");
|
153
172
|
}
|
154
|
-
this.editorBinPath = bin
|
173
|
+
this.editorBinPath = bin;
|
155
174
|
}
|
156
|
-
return this.editorBinPath
|
175
|
+
return this.editorBinPath;
|
157
176
|
}
|
158
177
|
|
159
178
|
async exec(options = {}) {
|
160
179
|
if (options.help) {
|
161
|
-
return this.showHelp()
|
180
|
+
return this.showHelp();
|
162
181
|
}
|
163
|
-
let currentEditor
|
182
|
+
let currentEditor;
|
164
183
|
try {
|
165
184
|
this.validate(options, {
|
166
|
-
path: true
|
167
|
-
})
|
168
|
-
currentEditor = process.env.EDITOR
|
185
|
+
path: true,
|
186
|
+
});
|
187
|
+
currentEditor = process.env.EDITOR;
|
169
188
|
if (options.internal) {
|
170
|
-
process.env.EDITOR = this.getTinyCliEditorBinPath()
|
189
|
+
process.env.EDITOR = this.getTinyCliEditorBinPath();
|
171
190
|
} else if (options.editor) {
|
172
|
-
process.env.EDITOR = options.editor
|
191
|
+
process.env.EDITOR = options.editor;
|
173
192
|
}
|
174
193
|
if (!process.env.EDITOR) {
|
175
|
-
let result = await execAsync(
|
194
|
+
let result = await execAsync("which", __dirname, ["nano"]);
|
176
195
|
if (!result.message || result.code === 1) {
|
177
|
-
result = await execAsync(
|
196
|
+
result = await execAsync("which", __dirname, ["vim"]);
|
178
197
|
if (!result.message || result.code === 1) {
|
179
|
-
throw new Error(
|
198
|
+
throw new Error(
|
199
|
+
'No text editor found. Set up the EDITOR env variable or use the -e option. Type "edit -h" for more options.'
|
200
|
+
);
|
180
201
|
} else {
|
181
|
-
process.env.EDITOR =
|
202
|
+
process.env.EDITOR = "vim";
|
182
203
|
}
|
183
204
|
} else {
|
184
|
-
process.env.EDITOR =
|
205
|
+
process.env.EDITOR = "nano";
|
185
206
|
}
|
186
207
|
}
|
187
|
-
await this.edit(options)
|
208
|
+
await this.edit(options);
|
188
209
|
} catch (e) {
|
189
|
-
this.Logger.red(e.message)
|
210
|
+
this.Logger.red(e.message);
|
190
211
|
}
|
191
212
|
// eslint-disable-next-line require-atomic-updates
|
192
|
-
process.env.EDITOR = currentEditor
|
193
|
-
await this.prompt.run()
|
213
|
+
process.env.EDITOR = currentEditor;
|
214
|
+
await this.prompt.run();
|
194
215
|
}
|
195
216
|
}
|
196
217
|
|
197
|
-
module.exports = Edit
|
198
|
-
|
199
|
-
|
218
|
+
module.exports = Edit;
|