Skip to main content

quorum_core/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:status",
38        summary: "Shows uptime and basic server info.",
39        description: "Prints how long the server has been running, what address it is listening on, and whether testing mode is active.",
40        usage: "server:status",
41        requires_auth: false,
42        requires_admin: false,
43        params: &[],
44    },
45    CommandEntry {
46        command: "server:logout",
47        summary: "Ends the current operator session.",
48        description: "Clears the authenticated session immediately. Any subsequent write commands will require logging in again.",
49        usage: "server:logout",
50        requires_auth: true,
51        requires_admin: false,
52        params: &[],
53    },
54    CommandEntry {
55        command: "server:shutdown",
56        summary: "Gracefully shuts the server down.",
57        description: "Signals the server to stop accepting new requests, waits for in-flight requests to complete, flushes logs, and exits cleanly.",
58        usage: "server:shutdown",
59        requires_auth: true,
60        requires_admin: true,
61        params: &[],
62    },
63    CommandEntry {
64        command: "server:logs",
65        summary: "Displays recent server logs.",
66        description: "Prints logs in order from most recent to oldest, allowing for optional filter for last X days.",
67        usage: "server:logs [days]",
68        requires_auth: false,
69        requires_admin: false,
70        params: &[("days", "Optional number of days to display logs for")],
71    },
72    CommandEntry {
73        command: "server:audit",
74        summary: "Displays recent audit logs.",
75        description: "Prints audit logs in order from most recent to oldest, allowing for optional filter for last X days.",
76        usage: "server:audit [days]",
77        requires_auth: false,
78        requires_admin: false,
79        params: &[("days", "Optional number of days to display audit logs for")],
80    },
81    // --db--
82    CommandEntry {
83        command: "db:stats",
84        summary: "Displays database statistics.",
85        description: "Prints the number of rows in each table, total row count, and estimated size of each table and database.",
86        usage: "db:stats",
87        requires_auth: false,
88        requires_admin: false,
89        params: &[],
90    },
91    CommandEntry {
92        command: "db:table",
93        summary: "Displays records from a specific table.",
94        description: "Prints the records from the specified table, with an option to view a specific page of results.",
95        usage: "db:table <name>, <page>",
96        requires_auth: false,
97        requires_admin: false,
98        params: &[
99            ("name", "The name of the table to display"),
100            ("page", "The page of results to display"),
101        ],
102    },
103    // --user--
104    CommandEntry {
105        command: "user:delete",
106        summary: "Deletes a user account.",
107        description: "Removes a user account from the database. This action is irreversible.",
108        usage: "user:delete <id>",
109        requires_auth: true,
110        requires_admin: true,
111        params: &[("id", "The ID of the user to delete")],
112    },
113    // --test--
114    CommandEntry {
115        command: "test:run",
116        summary: "Runs functional tests on the server.",
117        description: "Executes a suite of functional tests to verify that the server is operating correctly. This is only available if testing mode is enabled.",
118        usage: "test:run",
119        requires_auth: false,
120        requires_admin: false,
121        params: &[],
122    },
123];
124
125/// Prints a summary of all available commands, grouped by namespace.
126///
127/// This is used when the user uses the `help` command with no parameters given.
128pub fn print_all() {
129    println!();
130    println!("{}", "  Available Commands".cyan().bold());
131    println!(
132        "{}",
133        "  ─────────────────────────────────────────────────────".dimmed()
134    );
135
136    let namespaces = ["help", "server", "db", "user", "test"];
137
138    for ns in namespaces {
139        println!();
140        println!("  {}", ns.white().bold());
141
142        for entry in COMMANDS {
143            let ns_prefix = format!("{}:", ns);
144            let belongs = entry.command == ns
145                || entry.command.starts_with(&ns_prefix)
146                || (ns == "help" && entry.command.starts_with("help "));
147
148            if belongs {
149                let auth_marker = if entry.requires_auth {
150                    " *".yellow().to_string()
151                } else {
152                    String::new()
153                };
154                println!(
155                    "    {:<30} {}{}",
156                    entry.command.green(),
157                    entry.summary.dimmed(),
158                    auth_marker
159                );
160            }
161        }
162    }
163
164    println!();
165    println!(
166        "  {} {}",
167        "*".yellow(),
168        "marked commands require server:login before use.".dimmed()
169    );
170    println!(
171        "  {}",
172        "Run `help <command>` for detailed usage on any command.".dimmed()
173    );
174    println!();
175}
176
177/// Prints detailed help for a specific command, including its description, usage, parameters, and auth requirements.
178///
179/// This is used when the user uses the `help` command with a specific command name as a parameter.
180pub fn print_command(command: &str) {
181    let entry = COMMANDS.iter().find(|e| {
182        e.command == command
183            || e.command == format!("server:{}", command)
184            || e.command == format!("help {}", command)
185    });
186
187    match entry {
188        None => {
189            println!("{} {}", "No help entry found for:".red(), command.white());
190            println!("{}", "Run `help` to see all available commands.".dimmed());
191        }
192        Some(e) => {
193            println!();
194            println!("  {}", e.command.cyan().bold());
195            println!(
196                "{}",
197                "  ─────────────────────────────────────────────────────".dimmed()
198            );
199            println!(
200                "  {:<16} {}",
201                "Description:".white(),
202                e.description.dimmed()
203            );
204            println!("  {:<16} {}", "Usage:".white(), e.usage.green());
205            println!(
206                "  {:<16} {}",
207                "Auth required:".white(),
208                if e.requires_auth {
209                    "yes".yellow().to_string()
210                } else {
211                    "no".dimmed().to_string()
212                }
213            );
214
215            println!(
216                "  {:<16} {}",
217                "Admin permissions required:".white(),
218                if e.requires_admin {
219                    "yes".yellow().to_string()
220                } else {
221                    "no".dimmed().to_string()
222                }
223            );
224
225            if !e.params.is_empty() {
226                println!("  {}", "Parameters:".white());
227                for (name, desc) in e.params {
228                    println!("    {:<16} {}", name.green(), desc.dimmed());
229                }
230            }
231
232            println!();
233        }
234    }
235}