Skip to main content

quorum_public/cli/
help.rs

1//! Main cli file used for getting help with server commands
2
3use colored::Colorize;
4
5struct CommandEntry {
6    command: &'static str,                           //full command
7    summary: &'static str,                           //one line description
8    description: &'static str,                       //the full command description
9    usage: &'static str,                             //example usage
10    requires_auth: bool,                             //whether login is required first
11    requires_admin: bool,                            //whether admin privileges are required
12    params: &'static [(&'static str, &'static str)], //parameter names and what they mean
13}
14
15const COMMANDS: &[CommandEntry] = &[
16    // --help--
17    CommandEntry {
18        command: "help",
19        summary: "Lists all available commands.",
20        description: "Prints a summary of every available command, grouped by namespace.",
21        usage: "help",
22        requires_auth: false,
23        requires_admin: false,
24        params: &[],
25    },
26    CommandEntry {
27        command: "help <command>",
28        summary: "Shows detailed help for a specific command.",
29        description: "Prints the full description, usage, parameters, and auth requirement for the given command.",
30        usage: "help server:status",
31        requires_auth: false,
32        requires_admin: false,
33        params: &[("command", "The command to look up, e.g. server:status")],
34    },
35    // --server--
36    CommandEntry {
37        command: "server:update-database",
38        summary: "Updates server to use updated database.",
39        description: "Reinitializes database for updating purposes, an identical process to startup, so that the server can use the most up to date database.",
40        usage: "server:update-database",
41        requires_auth: false,
42        requires_admin: false,
43        params: &[],
44    },
45    CommandEntry {
46        command: "server:signup",
47        summary: "Creates a new user account.",
48        description: "Prompts for a username, password, and optional email address to create a new user account.",
49        usage: "server:signup",
50        requires_auth: false,
51        requires_admin: false,
52        params: &[],
53    },
54    CommandEntry {
55        command: "server:login",
56        summary: "Authenticates an operator session in the terminal.",
57        description: "Prompts for a username and password and verifies them against the database. On success, grants access to write/destructive commands for the next 20 minutes of inactivity.",
58        usage: "server:login",
59        requires_auth: false,
60        requires_admin: false,
61        params: &[],
62    },
63    CommandEntry {
64        command: "server:status",
65        summary: "Shows uptime and basic server info.",
66        description: "Prints how long the server has been running, what address it is listening on, and whether testing mode is active.",
67        usage: "server:status",
68        requires_auth: false,
69        requires_admin: false,
70        params: &[],
71    },
72    CommandEntry {
73        command: "server:logout",
74        summary: "Ends the current operator session.",
75        description: "Clears the authenticated session immediately. Any subsequent write commands will require logging in again.",
76        usage: "server:logout",
77        requires_auth: true,
78        requires_admin: false,
79        params: &[],
80    },
81    CommandEntry {
82        command: "server:shutdown",
83        summary: "Gracefully shuts the server down.",
84        description: "Signals the server to stop accepting new requests, waits for in-flight requests to complete, flushes logs, and exits cleanly.",
85        usage: "server:shutdown",
86        requires_auth: true,
87        requires_admin: true,
88        params: &[],
89    },
90    CommandEntry {
91        command: "server:logs",
92        summary: "Displays recent server logs.",
93        description: "Prints logs in order from most recent to oldest, allowing for optional filter for last X days.",
94        usage: "server:logs [days]",
95        requires_auth: false,
96        requires_admin: false,
97        params: &[("days", "Optional number of days to display logs for")],
98    },
99    CommandEntry {
100        command: "server:audit",
101        summary: "Displays recent audit logs.",
102        description: "Prints audit logs in order from most recent to oldest, allowing for optional filter for last X days.",
103        usage: "server:audit [days]",
104        requires_auth: false,
105        requires_admin: false,
106        params: &[("days", "Optional number of days to display audit logs for")],
107    },
108    // --db--
109    CommandEntry {
110        command: "db:stats",
111        summary: "Displays database statistics.",
112        description: "Prints the number of rows in each table, total row count, and estimated size of each table and database.",
113        usage: "db:stats",
114        requires_auth: false,
115        requires_admin: false,
116        params: &[],
117    },
118    CommandEntry {
119        command: "db:table",
120        summary: "Displays records from a specific table.",
121        description: "Prints the records from the specified table, with an option to view a specific page of results.",
122        usage: "db:table <name>, <page>",
123        requires_auth: false,
124        requires_admin: false,
125        params: &[
126            ("name", "The name of the table to display"),
127            ("page", "The page of results to display"),
128        ],
129    },
130    CommandEntry {
131        command: "db:delete",
132        summary: "Deletes the database and resets it to new",
133        description: "Deletes the database and resets it to a new state. This action is irreversible and will remove all data.",
134        usage: "db:delete",
135        requires_auth: true,
136        requires_admin: true,
137        params: &[],
138    },
139    // --user--
140    CommandEntry {
141        command: "user:delete",
142        summary: "Deletes a user account.",
143        description: "Removes a user account from the database. This action is irreversible.",
144        usage: "user:delete <id>",
145        requires_auth: true,
146        requires_admin: true,
147        params: &[("id", "The ID of the user to delete")],
148    },
149    // --test--
150    CommandEntry {
151        command: "test:run",
152        summary: "Runs functional tests on the server.",
153        description: "Executes a suite of functional tests to verify that the server is operating correctly. This is only available if testing mode is enabled.",
154        usage: "test:run",
155        requires_auth: false,
156        requires_admin: false,
157        params: &[],
158    },
159    // --config--
160    CommandEntry {
161        command: "config:show",
162        summary: "Displays the current server configuration.",
163        description: "Prints the current server configuration settings.",
164        usage: "config:show",
165        requires_auth: true,
166        requires_admin: true,
167        params: &[],
168    },
169    CommandEntry {
170        command: "config:<key>",
171        summary: "Sets a configuration value.",
172        description: "Updates a specific configuration setting in the server using the format `config:<key> <value>`. For example: `config:server_port 8080`. This action requires admin privileges.",
173        usage: "config:<key> <value>",
174        requires_auth: true,
175        requires_admin: true,
176        params: &[("value", "The new value for the configuration key")],
177    },
178];
179
180/// Prints a summary of all available commands, grouped by namespace.
181///
182/// This is used when the user uses the `help` command with no parameters given.
183pub fn print_all() {
184    println!();
185    println!("{}", "  Available Commands".cyan().bold());
186    println!(
187        "{}",
188        "  ─────────────────────────────────────────────────────".dimmed()
189    );
190
191    let namespaces = ["help", "server", "db", "user", "test", "config"];
192
193    for ns in namespaces {
194        println!();
195        println!("  {}", ns.white().bold());
196
197        for entry in COMMANDS {
198            let ns_prefix = format!("{}:", ns);
199            let belongs = entry.command == ns
200                || entry.command.starts_with(&ns_prefix)
201                || (ns == "help" && entry.command.starts_with("help "));
202
203            if belongs {
204                let auth_marker = if entry.requires_auth {
205                    " *".yellow().to_string()
206                } else {
207                    String::new()
208                };
209                println!(
210                    "    {:<30} {}{}",
211                    entry.command.green(),
212                    entry.summary.dimmed(),
213                    auth_marker
214                );
215            }
216        }
217    }
218
219    println!();
220    println!(
221        "  {} {}",
222        "*".yellow(),
223        "marked commands require server:login before use.".dimmed()
224    );
225    println!(
226        "  {}",
227        "Run `help <command>` for detailed usage on any command.".dimmed()
228    );
229    println!();
230}
231
232/// Prints detailed help for a specific command, including its description, usage, parameters, and auth requirements.
233///
234/// This is used when the user uses the `help` command with a specific command name as a parameter.
235pub fn print_command(command: &str) {
236    let entry = COMMANDS.iter().find(|e| {
237        e.command == command
238            || e.command == format!("server:{}", command)
239            || e.command == format!("help {}", command)
240    });
241
242    match entry {
243        None => {
244            println!("{} {}", "No help entry found for:".red(), command.white());
245            println!("{}", "Run `help` to see all available commands.".dimmed());
246        }
247        Some(e) => {
248            println!();
249            println!("  {}", e.command.cyan().bold());
250            println!(
251                "{}",
252                "  ─────────────────────────────────────────────────────".dimmed()
253            );
254            println!(
255                "  {:<16} {}",
256                "Description:".white(),
257                e.description.dimmed()
258            );
259            println!("  {:<16} {}", "Usage:".white(), e.usage.green());
260            println!(
261                "  {:<16} {}",
262                "Auth required:".white(),
263                if e.requires_auth {
264                    "yes".yellow().to_string()
265                } else {
266                    "no".dimmed().to_string()
267                }
268            );
269
270            println!(
271                "  {:<16} {}",
272                "Admin permissions required:".white(),
273                if e.requires_admin {
274                    "yes".yellow().to_string()
275                } else {
276                    "no".dimmed().to_string()
277                }
278            );
279
280            if !e.params.is_empty() {
281                println!("  {}", "Parameters:".white());
282                for (name, desc) in e.params {
283                    println!("    {:<16} {}", name.green(), desc.dimmed());
284                }
285            }
286
287            println!();
288        }
289    }
290}