Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_steel/src/srv/ws/syntax.rs

18.2 KiB, 59 runs

created by r1870400018:1001, 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

1use oxedyne_fe2o3_core::prelude::*;
2use oxedyne_fe2o3_jdat::{
3 prelude::*,
4 version::SemVer,
5};
6use oxedyne_fe2o3_syntax::{
7// arg::{
8// Arg,
9// ArgConfig,
10// },
11 cmd::{
12 Cmd,
13 CmdConfig,
14 },
15 core::{
16 Syntax,
17 SyntaxRef,
18 },
19};
20
21#[derive(Clone, Debug)]
22pub struct WebSocketSyntax;
23
24impl WebSocketSyntax {
25
26 pub fn new(
27 name: &str,
28 ver: &SemVer,
29 about: &str,
30 )
31 -> Outcome<SyntaxRef>
32 {
33 let mut s = Syntax::new(name).ver(*ver).about(about);
34 s = res!(s.with_default_help_cmd());
35
36 // ┌───────────────────────┐
37 // │ CONTROL │
38 // └───────────────────────┘
39
40 // ---------------------------------------------------------------------------------------------
41 // Command: exit
42 // ---------------------------------------------------------------------------------------------
43 let cmd = Cmd::from(CmdConfig {
44 name: fmt!("exit"),
45 help: Some(fmt!("Shutdown the app and exit, or use Ctrl+C, Ctrl+D")),
46 cat: fmt!("Control"),
47 ..Default::default()
48 });
49 s = res!(s.add_cmd(cmd));
50 // =============================================================================================
51
52 // ┌───────────────────────┐
53 // │ DEVELOPMENT │
54 // └───────────────────────┘
55
56 // ---------------------------------------------------------------------------------------------
57 // Command: dev_connect
58 // ---------------------------------------------------------------------------------------------
59 let cmd = Cmd::from(CmdConfig {
60 name: fmt!("dev_connect"),
61 help: Some(fmt!("Initialize dev mode refresh connection.")),
62 cat: fmt!("Development"),
63 ..Default::default()
64 });
65 s = res!(s.add_cmd(cmd));
66 // ---------------------------------------------------------------------------------------------
67 // Command: dev_ping
68 // ---------------------------------------------------------------------------------------------
69 let cmd = Cmd::from(CmdConfig {
70 name: fmt!("dev_ping"),
71 help: Some(fmt!("Keep dev mode connection alive.")),
72 cat: fmt!("Development"),
73 ..Default::default()
74 });
75 s = res!(s.add_cmd(cmd));
76
77 // ┌───────────────────────┐
78 // │ GENERAL IO │
79 // └───────────────────────┘
80
81 // ---------------------------------------------------------------------------------------------
82 // Command: data
83 // ---------------------------------------------------------------------------------------------
84 let cmd = Cmd::from(CmdConfig {
85 name: fmt!("data"),
86 help: Some(fmt!("Data retrieved from database.")),
87 vals: vec![(Kind::Unknown, fmt!("Retrieved data")).into()],
88 cat: fmt!("Database IO"),
89 ..Default::default()
90 });
91 s = res!(s.add_cmd(cmd));
92 // ---------------------------------------------------------------------------------------------
93 // Command: info
94 // ---------------------------------------------------------------------------------------------
95 let cmd = Cmd::from(CmdConfig {
96 name: fmt!("info"),
97 help: Some(fmt!("For your information.")),
98 vals: vec![(Kind::Str, fmt!("Information message")).into()],
99 cat: fmt!("General IO"),
100 ..Default::default()
101 });
102 s = res!(s.add_cmd(cmd));
103 // ---------------------------------------------------------------------------------------------
104 // Command: error
105 // ---------------------------------------------------------------------------------------------
106 let cmd = Cmd::from(CmdConfig {
107 name: fmt!("error"),
108 help: Some(fmt!("Error.")),
109 vals: vec![(Kind::Str, fmt!("Error message")).into()],
110 cat: fmt!("General IO"),
111 ..Default::default()
112 });
113 s = res!(s.add_cmd(cmd));
114 // ---------------------------------------------------------------------------------------------
115 // Command: echo
116 // ---------------------------------------------------------------------------------------------
117 let cmd = Cmd::from(CmdConfig {
118 name: fmt!("echo"),
119 help: Some(fmt!("Echo the incoming message.")),
120 vals: vec![(Kind::Str, fmt!("Text to echo")).into()],
121 cat: fmt!("General IO"),
122 ..Default::default()
123 });
124 s = res!(s.add_cmd(cmd));
125 // =============================================================================================
126
127 // ┌───────────────────────┐
128 // │ DATABASE IO │
129 // └───────────────────────┘
130
131 // ---------------------------------------------------------------------------------------------
132 // Command: insert
133 // ---------------------------------------------------------------------------------------------
134 let cmd = Cmd::from(CmdConfig {
135 name: fmt!("insert"),
136 help: Some(fmt!("Insert a key-value pair into the database.")),
137 vals: vec![
138 (Kind::Unknown, fmt!("Key")).into(),
139 (Kind::Unknown, fmt!("Value")).into(),
140 ],
141 cat: fmt!("Database IO"),
142 ..Default::default()
143 });
144 s = res!(s.add_cmd(cmd));
145 // =============================================================================================
146
147 // ---------------------------------------------------------------------------------------------
148 // Command: get_data
149 // ---------------------------------------------------------------------------------------------
150 let cmd = Cmd::from(CmdConfig {
151 name: fmt!("get_data"),
152 help: Some(fmt!("Get database value for given key daticle.")),
153 vals: vec![(Kind::Unknown, fmt!("Key")).into()],
154 cat: fmt!("Database IO"),
155 ..Default::default()
156 });
157 s = res!(s.add_cmd(cmd));
158 // =============================================================================================
159
160 // ┌───────────────────────┐
161 // │ SESSION IO │
162 // └───────────────────────┘
163
164 // ---------------------------------------------------------------------------------------------
165 // Command: sess_get
166 // ---------------------------------------------------------------------------------------------
167 // Reads a value from the caller's session-scoped keyspace. The
168 // server automatically prefixes the caller's session id (taken from
169 // the HttpOnly session cookie attached at the WebSocket upgrade),
170 // so the client cannot cross into another user's namespace.
171 let cmd = Cmd::from(CmdConfig {
172 name: fmt!("sess_get"),
173 help: Some(fmt!("Read a value from the caller's session-scoped storage.")),
174 vals: vec![(Kind::Str, fmt!("Key (string)")).into()],
175 cat: fmt!("Session IO"),
176 ..Default::default()
177 });
178 s = res!(s.add_cmd(cmd));
179
180 // ---------------------------------------------------------------------------------------------
181 // Command: sess_put
182 // ---------------------------------------------------------------------------------------------
183 // Writes a (key, value) pair into the caller's session-scoped
184 // keyspace. The key must be a string; the value can be any Dat.
185 let cmd = Cmd::from(CmdConfig {
186 name: fmt!("sess_put"),
187 help: Some(fmt!("Write a (key, value) pair into session-scoped storage.")),
188 vals: vec![
189 (Kind::Str, fmt!("Key")).into(),
190 (Kind::Unknown, fmt!("Value")).into(),
191 ],
192 cat: fmt!("Session IO"),
193 ..Default::default()
194 });
195 s = res!(s.add_cmd(cmd));
196 // =============================================================================================
197
198 // ┌───────────────────────┐
199 // │ USER IO │
200 // └───────────────────────┘
201
202 // ---------------------------------------------------------------------------------------------
203 // Command: user_get
204 // ---------------------------------------------------------------------------------------------
205 // Reads a value from the authenticated user's keyspace. The server
206 // looks up the session's bound user via `sess_meta:<sid>` and
207 // prefixes the request with `user:<username>:`. Rejects when the
208 // session is not authenticated.
209 let cmd = Cmd::from(CmdConfig {
210 name: fmt!("user_get"),
211 help: Some(fmt!("Read a value from the authenticated user's storage.")),
212 vals: vec![(Kind::Str, fmt!("Key (string)")).into()],
213 cat: fmt!("User IO"),
214 ..Default::default()
215 });
216 s = res!(s.add_cmd(cmd));
217
218 // ---------------------------------------------------------------------------------------------
219 // Command: user_put
220 // ---------------------------------------------------------------------------------------------
221 // Writes a (key, value) pair into the authenticated user's
222 // keyspace. The server scopes the key by the session-bound user
223 // and rejects if the session is not authenticated.
224 let cmd = Cmd::from(CmdConfig {
225 name: fmt!("user_put"),
226 help: Some(fmt!("Write a (key, value) pair into user-scoped storage.")),
227 vals: vec![
228 (Kind::Str, fmt!("Key")).into(),
229 (Kind::Unknown, fmt!("Value")).into(),
230 ],
231 cat: fmt!("User IO"),
232 ..Default::default()
233 });
234 s = res!(s.add_cmd(cmd));
235 // =============================================================================================
236
237 // ┌───────────────────────┐
238 // │ AUTH │
239 // └───────────────────────┘
240
241 // ---------------------------------------------------------------------------------------------
242 // Command: register
243 // ---------------------------------------------------------------------------------------------
244 // Create a new user record. The passphrase is hashed with Argon2id
245 // before storage; the plain passphrase is never written to disk.
246 let cmd = Cmd::from(CmdConfig {
247 name: fmt!("register"),
248 help: Some(fmt!("Create a new user record keyed by username.")),
249 vals: vec![
250 (Kind::Str, fmt!("Username")).into(),
251 (Kind::Str, fmt!("Passphrase")).into(),
252 ],
253 cat: fmt!("Auth"),
254 ..Default::default()
255 });
256 s = res!(s.add_cmd(cmd));
257
258 // ---------------------------------------------------------------------------------------------
259 // Command: login
260 // ---------------------------------------------------------------------------------------------
261 // Verify credentials and bind the current session to a user. A
262 // successful login writes a `sess_meta:<sid>` record recording
263 // which user the session is now acting as.
264 let cmd = Cmd::from(CmdConfig {
265 name: fmt!("login"),
266 help: Some(fmt!("Verify credentials and bind the current session to the user.")),
267 vals: vec![
268 (Kind::Str, fmt!("Username")).into(),
269 (Kind::Str, fmt!("Passphrase")).into(),
270 ],
271 cat: fmt!("Auth"),
272 ..Default::default()
273 });
274 s = res!(s.add_cmd(cmd));
275
276 // ---------------------------------------------------------------------------------------------
277 // Command: logout
278 // ---------------------------------------------------------------------------------------------
279 // Clear the session-to-user binding for the caller's session. The
280 // underlying HttpOnly cookie is not touched; the session remains
281 // anonymous until the next successful login.
282 let cmd = Cmd::from(CmdConfig {
283 name: fmt!("logout"),
284 help: Some(fmt!("Clear the session-to-user binding for this session.")),
285 cat: fmt!("Auth"),
286 ..Default::default()
287 });
288 s = res!(s.add_cmd(cmd));
289
290 // ---------------------------------------------------------------------------------------------
291 // Command: whoami
292 // ---------------------------------------------------------------------------------------------
293 // Report whether the caller's session is authenticated and, if so,
294 // under which username. The session id itself is never returned.
295 let cmd = Cmd::from(CmdConfig {
296 name: fmt!("whoami"),
297 help: Some(fmt!("Report the authenticated user for this session, if any.")),
298 cat: fmt!("Auth"),
299 ..Default::default()
300 });
301 s = res!(s.add_cmd(cmd));
302 // =============================================================================================
303
304 // ┌───────────────────────┐
305 // │ TERMINAL │
306 // └───────────────────────┘
307
308 // ---------------------------------------------------------------------------------------------
309 // Command: term_new
310 // ---------------------------------------------------------------------------------------------
311 // Create a new terminal session (tmux). Returns the session
312 // name in the data response.
313 let cmd = Cmd::from(CmdConfig {
314 name: fmt!("term_new"),
315 help: Some(fmt!("Create a new terminal session.")),
316 cat: fmt!("Terminal"),
317 ..Default::default()
318 });
319 s = res!(s.add_cmd(cmd));
320 // =============================================================================================
321
322 // ---------------------------------------------------------------------------------------------
323 // Command: term_list
324 // ---------------------------------------------------------------------------------------------
325 // List active terminal sessions. Returns a map with a
326 // "sessions" array of { "name": "goose-N" } entries.
327 let cmd = Cmd::from(CmdConfig {
328 name: fmt!("term_list"),
329 help: Some(fmt!("List active terminal sessions.")),
330 cat: fmt!("Terminal"),
331 ..Default::default()
332 });
333 s = res!(s.add_cmd(cmd));
334 // =============================================================================================
335
336 // ---------------------------------------------------------------------------------------------
337 // Command: term_close
338 // ---------------------------------------------------------------------------------------------
339 // Kill a terminal session by name.
340 let cmd = Cmd::from(CmdConfig {
341 name: fmt!("term_close"),
342 help: Some(fmt!("Kill a terminal session by name.")),
343 vals: vec![(Kind::Str, fmt!("Session name")).into()],
344 cat: fmt!("Terminal"),
345 ..Default::default()
346 });
347 s = res!(s.add_cmd(cmd));
348 // =============================================================================================
349
350 // ---------------------------------------------------------------------------------------------
351 // Command: term_set_name
352 // ---------------------------------------------------------------------------------------------
353 // Rename a terminal session.
354 let cmd = Cmd::from(CmdConfig {
355 name: fmt!("term_set_name"),
356 help: Some(fmt!("Rename a terminal session.")),
357 vals: vec![
358 (Kind::Str, fmt!("Old session name")).into(),
359 (Kind::Str, fmt!("New session name")).into(),
360 ],
361 cat: fmt!("Terminal"),
362 ..Default::default()
363 });
364 s = res!(s.add_cmd(cmd));
365 // =============================================================================================
366
367 // ---------------------------------------------------------------------------------------------
368 // Command: change_pass
369 // ---------------------------------------------------------------------------------------------
370 // Change the authenticated user's passphrase. Requires the
371 // old passphrase for verification and the new passphrase
372 // (entered twice on the client side).
373 let cmd = Cmd::from(CmdConfig {
374 name: fmt!("change_pass"),
375 help: Some(fmt!("Change the authenticated user's passphrase.")),
376 vals: vec![
377 (Kind::Str, fmt!("Old passphrase")).into(),
378 (Kind::Str, fmt!("New passphrase")).into(),
379 ],
380 cat: fmt!("Auth"),
381 ..Default::default()
382 });
383 s = res!(s.add_cmd(cmd));
384 // =============================================================================================
385
386 Ok(SyntaxRef::new(s))
387 }
388}