Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 591d3ac

Browse files
authored
Restrict general help content in REPL context (#5885)
Restrict general help in REPL context General help can be requested in 2 contexts, the command line, and a REPL, both having a different set of valid truffle commands. This commit 1) moves the source of truth for valid, excluded (in REPL) and valid REPL commands to a single module. 2) modifies the `displayGeneralHelp` function to be context aware and display the appropriate help. 3) Updates tests and webpack to use the new source of truth. ## packages/core/lib/commands/commands.js - define the single source of truth for valid, excluded and console only truffle commands that is easy to maintain. ## packages/core/lib/command-utils.js - update logic to use the single source of truth - modify `displayGeneralHelp()` to accept a flag specifying whether it is run in a REPL. If in a REPL, the logic will show help for console-only truffle commands. ## packages/core/lib/commands/console/run.js - use command source of truth instead of calculating ## packages/core/lib/commands/develop/run.js - use command source of truth instead of calculating ## packages/core/lib/console-child.js - modify `displayGeneralHelp()` to accept an `isREPL` option, which is used to display help for REPL commands or command line commands. ## packages/core/lib/console.js - refactor to use truffle command source of truth and modified error messages for using excluded and invalid commands in the REPL ## misc - packages/core/test/commands.js - packages/core/test/lib/console.js - packages/truffle/webpack.config.js - refactor to use command source of truth.
1 parent 2f38379 commit 591d3ac

File tree

10 files changed

+79
-77
lines changed

10 files changed

+79
-77
lines changed

packages/core/lib/command-utils.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ const { extractFlags } = require("./utils/utils"); // contains utility methods
55
const globalCommandOptions = require("./global-command-options");
66
const debugModule = require("debug");
77
const debug = debugModule("core:command:run");
8-
const commands = require("./commands/commands");
8+
const {
9+
validTruffleCommands,
10+
validTruffleConsoleCommands
11+
} = require("./commands/commands");
912
const Web3 = require("web3");
1013
const TruffleError = require("@truffle/error");
1114

@@ -116,11 +119,11 @@ const getCommand = ({ inputStrings, options, noAliases }) => {
116119
// for inferring the command.
117120
if (firstInputString === "-v" || firstInputString === "--version") {
118121
chosenCommand = "version";
119-
} else if (commands.includes(firstInputString)) {
122+
} else if (validTruffleCommands.includes(firstInputString)) {
120123
chosenCommand = firstInputString;
121124
} else if (noAliases !== true) {
122125
let currentLength = 1;
123-
const availableCommandNames = commands;
126+
const availableCommandNames = validTruffleCommands;
124127

125128
// Loop through each letter of the input until we find a command
126129
// that uniquely matches.
@@ -294,8 +297,16 @@ const runCommand = async function (command, options) {
294297
return await command.run(options);
295298
};
296299

297-
const displayGeneralHelp = () => {
300+
/**
301+
* Display general help for Truffle commands
302+
* @param {Object} options - options object
303+
* @param {Boolean} options.isREPL - whether or not the help is being displayed in a REPL
304+
* @returns {void}
305+
*/
306+
const displayGeneralHelp = options => {
298307
const yargs = require("yargs/yargs")();
308+
const isREPL = options?.isREPL ?? false; //default to not displaying REPL commands
309+
const commands = isREPL ? validTruffleConsoleCommands : validTruffleCommands;
299310
commands.forEach(command => {
300311
// Exclude "install" and "publish" commands from the generated help list
301312
// because they have been deprecated/removed.

packages/core/lib/commands/commands.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// The list of commands that Truffle supports
2-
module.exports = [
1+
const validTruffleCommands = [
32
"build",
43
"compile",
54
"config",
@@ -26,3 +25,23 @@ module.exports = [
2625
"version",
2726
"watch"
2827
];
28+
29+
//List of truffle commands that are excluded from the console REPLS.
30+
const excludedTruffleConsoleCommands = [
31+
"console",
32+
"dashboard",
33+
"db",
34+
"develop",
35+
"init",
36+
"watch"
37+
];
38+
39+
const validTruffleConsoleCommands = validTruffleCommands.filter(
40+
command => !excludedTruffleConsoleCommands.includes(command)
41+
);
42+
43+
module.exports = {
44+
excludedTruffleConsoleCommands,
45+
validTruffleCommands,
46+
validTruffleConsoleCommands
47+
};
+2-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
module.exports = async function (options) {
22
const OS = require("os");
3-
const { Console, excludedCommands } = require("../../console");
3+
const { Console } = require("../../console");
44
const { Environment } = require("@truffle/environment");
55
const TruffleError = require("@truffle/error");
6-
const commands = require("../commands");
76
const loadConfig = require("../../loadConfig");
87

98
if (options.url && options.network) {
@@ -19,15 +18,7 @@ module.exports = async function (options) {
1918
}
2019

2120
let config = loadConfig(options);
22-
23-
const allowedConsoleCommands = commands.filter(
24-
cmd => !excludedCommands.has(cmd)
25-
);
26-
2721
await Environment.detect(config);
28-
const c = new Console(
29-
allowedConsoleCommands,
30-
config.with({ noAliases: true })
31-
);
22+
const c = new Console(config.with({ noAliases: true }));
3223
return await c.start();
3324
};

packages/core/lib/commands/develop/run.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,11 @@ const {
66
} = require("../../configAdapter");
77

88
const runConsole = async (config, ganacheOptions) => {
9-
const { Console, excludedCommands } = require("../../console");
9+
const { Console } = require("../../console");
1010
const { Environment } = require("@truffle/environment");
1111

12-
const commands = require("../commands");
13-
const allowedConsoleCommands = commands.filter(
14-
cmd => !excludedCommands.has(cmd)
15-
);
16-
1712
await Environment.develop(config, ganacheOptions);
18-
const c = new Console(
19-
allowedConsoleCommands,
20-
config.with({ noAliases: true })
21-
);
13+
const c = new Console(config.with({ noAliases: true }));
2214
c.on("exit", () => process.exit());
2315
return await c.start();
2416
};

packages/core/lib/console-child.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const inputArguments = parseQuotesAndEscapes(input[1], escapeCharacters); //note
1818
// handle cases where input indicates the user wants to access Truffle's help
1919
const { displayHelp, inputStrings } = handleHelpInput({ inputArguments });
2020
if (displayHelp) {
21-
displayGeneralHelp();
21+
displayGeneralHelp({ isREPL: true });
2222
process.exit();
2323
}
2424

packages/core/lib/console.js

+24-22
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ const EventEmitter = require("events");
1515
const { spawn } = require("child_process");
1616
const Require = require("@truffle/require");
1717
const debug = require("debug")("console");
18-
const { getCommand, parseQuotesAndEscapes } = require("./command-utils");
19-
const validTruffleCommands = require("./commands/commands");
18+
const { parseQuotesAndEscapes } = require("./command-utils");
19+
const {
20+
excludedTruffleConsoleCommands,
21+
validTruffleConsoleCommands
22+
} = require("./commands/commands");
2023

2124
// Create an expression that returns a string when evaluated
2225
// by the REPL
2326
const makeIIFE = str => `(() => "${str}")()`;
2427

25-
const processInput = (input, allowedCommands) => {
28+
const processInput = input => {
2629
const words = input.trim().split(/\s+/);
2730

2831
// empty input
@@ -39,20 +42,30 @@ const processInput = (input, allowedCommands) => {
3942
}
4043

4144
const normalizedCommand = cmd.toLowerCase();
42-
if (validTruffleCommands.includes(normalizedCommand)) {
43-
return allowedCommands.includes(normalizedCommand)
44-
? words.slice(1).join(" ")
45-
: makeIIFE(`ℹ️ : '${cmd}' is not allowed within Truffle REPL`);
45+
const isExcludedInREPL =
46+
excludedTruffleConsoleCommands.includes(normalizedCommand);
47+
48+
if (isExcludedInREPL) {
49+
return makeIIFE(
50+
`ℹ️ : '${words[0]} ${cmd}' is not allowed in Console environment.`
51+
);
4652
}
47-
return makeIIFE(`ℹ️ : '${cmd}' is not a valid Truffle command`);
53+
54+
if (!validTruffleConsoleCommands.includes(normalizedCommand)) {
55+
return makeIIFE(
56+
`ℹ️ : '${words[0]} ${cmd}' is not a valid truffle command.`
57+
);
58+
}
59+
60+
return words.slice(1).join(" ");
4861
}
4962

5063
// an expression
5164
return input.trim();
5265
};
5366

5467
class Console extends EventEmitter {
55-
constructor(allowedCommands, options) {
68+
constructor(options) {
5669
super();
5770
EventEmitter.call(this);
5871

@@ -69,7 +82,6 @@ class Console extends EventEmitter {
6982
"build_directory"
7083
]);
7184

72-
this.allowedCommands = allowedCommands;
7385
this.options = options;
7486

7587
this.repl = null;
@@ -398,15 +410,8 @@ class Console extends EventEmitter {
398410
}
399411

400412
async interpret(input, context, filename, callback) {
401-
const processedInput = processInput(input, this.allowedCommands);
402-
if (
403-
this.allowedCommands.includes(processedInput.split(/\s+/)[0]) &&
404-
getCommand({
405-
inputStrings: processedInput.split(/\s+/),
406-
options: {},
407-
noAliases: this.options.noAliases
408-
}) !== null
409-
) {
413+
const processedInput = processInput(input);
414+
if (validTruffleConsoleCommands.includes(processedInput.split(/\s+/)[0])) {
410415
try {
411416
parseQuotesAndEscapes(processedInput); //we're just doing this to see
412417
//if it errors. unfortunately we need to throw out the result and recompute
@@ -526,9 +531,6 @@ class Console extends EventEmitter {
526531
}
527532
}
528533

529-
const excludedCommands = new Set(["console", "db", "init", "watch", "develop"]);
530-
531534
module.exports = {
532-
excludedCommands,
533535
Console
534536
};

packages/core/test/commands.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const {
33
prepareOptions,
44
runCommand
55
} = require("../lib/command-utils");
6-
const commandsArray = require("../lib/commands/commands");
6+
const { validTruffleCommands } = require("../lib/commands/commands");
77
const allCommands = require("../lib/commands");
88
const { assert } = require("chai");
99

@@ -14,13 +14,13 @@ describe("commands", function () {
1414
it("contains an array item for each command", function () {
1515
assert(
1616
Object.keys(allCommands).every(command =>
17-
commandsArray.includes(command)
17+
validTruffleCommands.includes(command)
1818
)
1919
);
2020
});
2121
it("contains a command for every array item", function () {
2222
assert(
23-
commandsArray.every(command =>
23+
validTruffleCommands.every(command =>
2424
Object.keys(allCommands).includes(command)
2525
)
2626
);

packages/core/test/lib/console.js

+5-18
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
const assert = require("chai").assert;
22
const path = require("path");
3-
const { Console, excludedCommands } = require("../../lib/console");
4-
const commands = require("../../lib/commands");
3+
const { Console } = require("../../lib/console");
54
const sinon = require("sinon");
65
const Config = require("@truffle/config");
76
const Web3 = require("web3");
87
const { Resolver } = require("@truffle/resolver");
98
const config = new Config();
109

11-
const allowedConsoleCommands = Object.keys(commands).filter(
12-
cmd => !excludedCommands.has(cmd)
13-
);
1410
let truffleConsole, consoleOptions;
1511

1612
describe("Console", function () {
@@ -40,7 +36,7 @@ describe("Console", function () {
4036
{ path: pathToMoreUserJs },
4137
{ path: pathToUserJs, as: "namespace" }
4238
];
43-
truffleConsole = new Console(allowedConsoleCommands, consoleOptions);
39+
truffleConsole = new Console(consoleOptions);
4440
sinon
4541
.stub(truffleConsole.interfaceAdapter, "getAccounts")
4642
.returns(["0x0"]);
@@ -86,10 +82,7 @@ describe("Console", function () {
8682
"test/sources/moreUserVariables.js"
8783
);
8884
otherConsoleOptions["require-none"] = true;
89-
otherTruffleConsole = new Console(
90-
allowedConsoleCommands,
91-
otherConsoleOptions
92-
);
85+
otherTruffleConsole = new Console(otherConsoleOptions);
9386
});
9487

9588
it("won't load any user-defined JS", async function () {
@@ -118,10 +111,7 @@ describe("Console", function () {
118111
config.working_directory,
119112
"test/sources/nameConflicts.js"
120113
);
121-
otherTruffleConsole = new Console(
122-
allowedConsoleCommands,
123-
otherConsoleOptions
124-
);
114+
otherTruffleConsole = new Console(otherConsoleOptions);
125115
});
126116

127117
it("won't let users clobber Truffle variables", async function () {
@@ -147,10 +137,7 @@ describe("Console", function () {
147137
provider: new Web3.providers.WebsocketProvider("ws://localhost:666"),
148138
resolver: new Resolver(config)
149139
});
150-
otherTruffleConsole = new Console(
151-
allowedConsoleCommands,
152-
otherConsoleOptions
153-
);
140+
otherTruffleConsole = new Console(otherConsoleOptions);
154141
});
155142

156143
it("accepts options.r", async function () {

packages/truffle/test/scenarios/commands/develop.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,19 @@ describe("truffle develop", function () {
7878
[
7979
{
8080
cmd: "console",
81-
expectedError: `ℹ️ : 'console' is not allowed within Truffle REPL`
81+
expectedError: `ℹ️ : 'truffle console' is not allowed in Console environment.`
8282
},
8383
{
8484
cmd: "CONSOLE",
85-
expectedError: `ℹ️ : 'CONSOLE' is not allowed within Truffle REPL`
85+
expectedError: `ℹ️ : 'truffle CONSOLE' is not allowed in Console environment.`
8686
},
8787
{
8888
cmd: "develop",
89-
expectedError: `ℹ️ : 'develop' is not allowed within Truffle REPL`
89+
expectedError: `ℹ️ : 'truffle develop' is not allowed in Console environment.`
9090
},
9191
{
9292
cmd: "alakazam",
93-
expectedError: `ℹ️ : 'alakazam' is not a valid Truffle command`
93+
expectedError: `ℹ️ : 'truffle alakazam' is not a valid truffle command.`
9494
},
9595
{
9696
cmd: "",

packages/truffle/webpack.config.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const webpack = require("webpack");
55
const pkg = require("./package.json");
66
const rootDir = path.join(__dirname, "../..");
77
const outputDir = path.join(__dirname, "build");
8-
const commands = require("../core/lib/commands/commands");
8+
const { validTruffleCommands } = require("../core/lib/commands/commands");
99
const truffleLibraryDirectory = path.join(
1010
__dirname,
1111
"../..",
@@ -27,7 +27,7 @@ const truffleRequireDistDirectory = path.join(
2727

2828
const ganacheConsoleSol = require.resolve("@ganache/console.log/console.sol");
2929

30-
const commandsEntries = commands.reduce((a, command) => {
30+
const commandsEntries = validTruffleCommands.reduce((a, command) => {
3131
a[command] = path.join(
3232
__dirname,
3333
"../..",

0 commit comments

Comments
 (0)