Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_steel/src/app/syntax.rs

13.9 KiB, 77 runs

created by r1870400018:959, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//use crate::srv::id;
2
3use oxedyne_fe2o3_core::prelude::*;
4use oxedyne_fe2o3_jdat::{
5 prelude::*,
6 version::SemVer,
7};
8use oxedyne_fe2o3_syntax::{
9 self,
10 Syntax,
11 SyntaxRef,
12 arg::{
13 Arg,
14 ArgConfig,
15 },
16 cmd::{
17 Cmd,
18 CmdConfig,
19 },
20};
21
22
23pub fn new_shell(
24 name: &str,
25 ver: &SemVer,
26 about: &str,
27)
28 -> Outcome<SyntaxRef>
29{
30 let s = res!(new_shell_raw(name, ver, about));
31 Ok(SyntaxRef::new(s))
32}
33
34pub fn new_shell_raw(
35 name: &str,
36 ver: &SemVer,
37 about: &str,
38)
39 -> Outcome<Syntax>
40{
41 let mut s = Syntax::new(name).ver(*ver).about(about);
42 s = res!(s.with_default_help_cmd());
43 s = res!(oxedyne_fe2o3_syntax::apps::file::generic_file_system(s));
44
45 // ┌───────────────────────┐
46 // │ CONTROL │
47 // └───────────────────────┘
48 // ---------------------------------------------------------------------------------------------
49 // Command: exit
50 // ---------------------------------------------------------------------------------------------
51 let cmd = Cmd::from(CmdConfig {
52 name: fmt!("exit"),
53 help: Some(fmt!("Shutdown the app and exit, or use Ctrl+C, Ctrl+D")),
54 cat: fmt!("Control"),
55 ..Default::default()
56 });
57 s = res!(s.add_cmd(cmd));
58 // =============================================================================================
59
60 // ---------------------------------------------------------------------------------------------
61 // Command: shell
62 // ---------------------------------------------------------------------------------------------
63 let cmd = Cmd::from(CmdConfig {
64 name: fmt!("shell"),
65 help: Some(fmt!("Start the app shell")),
66 cat: fmt!("Control"),
67 ..Default::default()
68 });
69 s = res!(s.add_cmd(cmd));
70 // =============================================================================================
71
72 // ---------------------------------------------------------------------------------------------
73 // Command: server
74 // ---------------------------------------------------------------------------------------------
75 let mut cmd = Cmd::from(CmdConfig {
76 name: fmt!("server"),
77 help: Some(fmt!("Start the app HTTPS server")),
78 cat: fmt!("Control"),
79 ..Default::default()
80 });
81 let a1 = Arg::from(ArgConfig {
82 name: fmt!("dev"),
83 hyph1: Some(fmt!("d")),
84 vals: vec![],
85 reqd: false,
86 help: Some(fmt!("Run server in developer mode.")),
87 ..Default::default()
88 });
89 cmd = res!(cmd.add_arg(a1));
90 s = res!(s.add_cmd(cmd));
91 // =============================================================================================
92
93 // ---------------------------------------------------------------------------------------------
94 // Command: cert
95 // ---------------------------------------------------------------------------------------------
96 let mut cmd = Cmd::from(CmdConfig {
97 name: fmt!("cert"),
98 help: Some(fmt!("Manage TLS certificates")),
99 cat: fmt!("TLS"),
100 ..Default::default()
101 });
102 let a1 = Arg::from(ArgConfig {
103 name: fmt!("create-dev"),
104 hyph1: Some(fmt!("d")),
105 vals: vec![],
106 reqd: false,
107 help: Some(fmt!("Create self-signed certificates for development.")),
108 ..Default::default()
109 });
110 cmd = res!(cmd.add_arg(a1));
111 s = res!(s.add_cmd(cmd));
112 // =============================================================================================
113
114 // ---------------------------------------------------------------------------------------------
115 // Command: acme
116 // ---------------------------------------------------------------------------------------------
117 let mut cmd = Cmd::from(CmdConfig {
118 name: fmt!("acme"),
119 help: Some(fmt!("Manage ACME (Let's Encrypt) certificate state")),
120 cat: fmt!("TLS"),
121 ..Default::default()
122 });
123 let a1 = Arg::from(ArgConfig {
124 name: fmt!("status"),
125 hyph1: Some(fmt!("s")),
126 vals: vec![],
127 reqd: false,
128 help: Some(fmt!("Print the configured ACME state and vhost hostnames.")),
129 ..Default::default()
130 });
131 let a2 = Arg::from(ArgConfig {
132 name: fmt!("renew"),
133 hyph1: Some(fmt!("r")),
134 vals: vec![],
135 reqd: false,
136 help: Some(fmt!("Clear the ACME cache so certs are re-issued on next start-up.")),
137 ..Default::default()
138 });
139 cmd = res!(cmd.add_arg(a1));
140 cmd = res!(cmd.add_arg(a2));
141 s = res!(s.add_cmd(cmd));
142
143 // ┌───────────────────────┐
144 // │ WALLET │
145 // └───────────────────────┘
146 // ---------------------------------------------------------------------------------------------
147 // Command: secrets
148 // ---------------------------------------------------------------------------------------------
149 let mut cmd = Cmd::from(CmdConfig {
150 name: fmt!("secrets"),
151 help: Some(fmt!("Manage wallet encrypted secrets.")),
152 cat: fmt!("Wallet"),
153 ..Default::default()
154 });
155 let a1 = Arg::from(ArgConfig {
156 name: fmt!("create"),
157 hyph1: Some(fmt!("c")),
158 vals: vec![(Kind::Str, fmt!("Name of secret for indexing")).into()],
159 reqd: false,
160 help: Some(fmt!("Interactively create a new encrypted secret.")),
161 ..Default::default()
162 });
163 let a2 = Arg::from(ArgConfig {
164 name: fmt!("recover"),
165 hyph1: Some(fmt!("r")),
166 vals: vec![(Kind::Str, fmt!("Name of secret for indexing")).into()],
167 reqd: false,
168 help: Some(fmt!("Interactively recover an encrypted secret.")),
169 ..Default::default()
170 });
171 cmd = res!(cmd.add_arg(a1));
172 cmd = res!(cmd.add_arg(a2));
173 s = res!(s.add_cmd(cmd));
174 // =============================================================================================
175
176 // ---------------------------------------------------------------------------------------------
177 // Command: unseal
178 // ---------------------------------------------------------------------------------------------
179 let cmd = Cmd::from(CmdConfig {
180 name: fmt!("unseal"),
181 help: Some(fmt!("Unwrap the wallet master key with an admin passphrase, so \
182 the server opens its databases when it starts. Optional: the server runs \
183 sealed as well, serving every static vhost while DB-backed routes answer \
184 503, and can be unsealed from the /admin dashboard afterwards.")),
185 cat: fmt!("Wallet"),
186 ..Default::default()
187 });
188 s = res!(s.add_cmd(cmd));
189 // =============================================================================================
190
191 // ---------------------------------------------------------------------------------------------
192 // Command: wallet
193 // ---------------------------------------------------------------------------------------------
194 let mut cmd = Cmd::from(CmdConfig {
195 name: fmt!("wallet"),
196 help: Some(fmt!("Manage the wallet file.")),
197 cat: fmt!("Wallet"),
198 ..Default::default()
199 });
200 let a1 = Arg::from(ArgConfig {
201 name: fmt!("migrate"),
202 hyph1: Some(fmt!("m")),
203 hyph2: Some(fmt!("migrate")),
204 vals: vec![],
205 reqd: false,
206 help: Some(fmt!("One-shot migrate a pre-admin-user wallet (the legacy \
207 app_hashes / wallet_pass_hashes layout) into the multi-admin layout, \
208 preserving the existing master key so no Ozone re-encryption is \
209 required.")),
210 ..Default::default()
211 });
212 cmd = res!(cmd.add_arg(a1));
213 s = res!(s.add_cmd(cmd));
214 // =============================================================================================
215
216 // ---------------------------------------------------------------------------------------------
217 // Command: admin
218 // ---------------------------------------------------------------------------------------------
219 let mut cmd = Cmd::from(CmdConfig {
220 name: fmt!("admin"),
221 help: Some(fmt!("Manage wallet admin entries (add, remove, list).")),
222 cat: fmt!("Wallet"),
223 ..Default::default()
224 });
225 let a1 = Arg::from(ArgConfig {
226 name: fmt!("add"),
227 hyph1: Some(fmt!("a")),
228 hyph2: Some(fmt!("add")),
229 vals: vec![(Kind::Str, fmt!("New admin name")).into()],
230 reqd: false,
231 help: Some(fmt!("Add a new admin entry wrapping the wallet master \
232 key under a freshly prompted password. The running session must \
233 have been unlocked by an admin holding the 'admin' scope.")),
234 ..Default::default()
235 });
236 let a2 = Arg::from(ArgConfig {
237 name: fmt!("remove"),
238 hyph1: Some(fmt!("r")),
239 hyph2: Some(fmt!("remove")),
240 vals: vec![(Kind::Str, fmt!("Admin name to remove")).into()],
241 reqd: false,
242 help: Some(fmt!("Remove an existing admin entry by name. The last \
243 remaining admin cannot be removed.")),
244 ..Default::default()
245 });
246 let a3 = Arg::from(ArgConfig {
247 name: fmt!("list"),
248 hyph1: Some(fmt!("l")),
249 hyph2: Some(fmt!("list")),
250 vals: vec![],
251 reqd: false,
252 help: Some(fmt!("List the names, scopes and expiry of every admin \
253 entry in the wallet.")),
254 ..Default::default()
255 });
256 let a4 = Arg::from(ArgConfig {
257 name: fmt!("scopes"),
258 hyph1: Some(fmt!("s")),
259 hyph2: Some(fmt!("scopes")),
260 vals: vec![(Kind::Str, fmt!("Comma-separated verb list")).into()],
261 reqd: false,
262 help: Some(fmt!("Scopes for a new admin, comma-separated. Well-known \
263 scopes: 'admin' (manage other admin entries, in CLI and dashboard); \
264 'dashboard.view' (log into the admin dashboard, read-only); \
265 'dashboard.admin' (log into the admin dashboard with mutations). \
266 Use '*' for operator-level access. Defaults to an empty scope \
267 list, which can unlock the wallet but cannot invoke any verb.")),
268 ..Default::default()
269 });
270 let a5 = Arg::from(ArgConfig {
271 name: fmt!("expires-in"),
272 hyph1: Some(fmt!("e")),
273 hyph2: Some(fmt!("expires-in")),
274 vals: vec![(Kind::U64, fmt!("Seconds until expiry")).into()],
275 reqd: false,
276 help: Some(fmt!("Expire the new admin after N seconds from now. \
277 A value of 0 (the default) means 'never expires'.")),
278 ..Default::default()
279 });
280 let a6 = Arg::from(ArgConfig {
281 name: fmt!("passwd"),
282 hyph1: Some(fmt!("p")),
283 hyph2: Some(fmt!("passwd")),
284 vals: vec![],
285 reqd: false,
286 help: Some(fmt!("Change the caller's own admin password in place. \
287 The caller is whichever admin unlocked the wallet at start-up. \
288 Scopes and expiry are preserved; only the wrap is replaced. \
289 Prompts for the new password twice.")),
290 ..Default::default()
291 });
292 cmd = res!(cmd.add_arg(a1));
293 cmd = res!(cmd.add_arg(a2));
294 cmd = res!(cmd.add_arg(a3));
295 cmd = res!(cmd.add_arg(a4));
296 cmd = res!(cmd.add_arg(a5));
297 cmd = res!(cmd.add_arg(a6));
298 s = res!(s.add_cmd(cmd));
299 // =============================================================================================
300
301 // ┌───────────────────────┐
302 // │ MAIL │
303 // └───────────────────────┘
304 // ---------------------------------------------------------------------------------------------
305 // Command: mailpass
306 // ---------------------------------------------------------------------------------------------
307 let mut cmd = Cmd::from(CmdConfig {
308 name: fmt!("mailpass"),
309 help: Some(fmt!("Hash an interactively-prompted password with Argon2id, ready \
310 to paste into the mail users file.")),
311 cat: fmt!("Mail"),
312 ..Default::default()
313 });
314 let a1 = Arg::from(ArgConfig {
315 name: fmt!("address"),
316 hyph1: Some(fmt!("a")),
317 vals: vec![(Kind::Str, fmt!("Email address")).into()],
318 reqd: true,
319 help: Some(fmt!("Email address (local@domain) the password belongs to.")),
320 ..Default::default()
321 });
322 let a2 = Arg::from(ArgConfig {
323 name: fmt!("delivery-dir"),
324 hyph1: Some(fmt!("d")),
325 vals: vec![(Kind::Str, fmt!("Relative directory under maildir_root")).into()],
326 reqd: true,
327 help: Some(fmt!("Per-user mailbox directory, relative to maildir_root.")),
328 ..Default::default()
329 });
330 cmd = res!(cmd.add_arg(a1));
331 cmd = res!(cmd.add_arg(a2));
332 s = res!(s.add_cmd(cmd));
333 // =============================================================================================
334
335 // ┌───────────────────────┐
336 // │ WORKSPACE │
337 // └───────────────────────┘
338 // ---------------------------------------------------------------------------------------------
339 // Command: vars
340 // ---------------------------------------------------------------------------------------------
341 let cmd = Cmd::from(CmdConfig {
342 name: fmt!("vars"),
343 help: Some(fmt!("Display variable names and values")),
344 cat: fmt!("Workspace"),
345 ..Default::default()
346 });
347 s = res!(s.add_cmd(cmd));
348 // =============================================================================================
349
350 Ok(s)
351}