CH-J Toolsgestión de servidores a través de SSH
Menú
Fuente publicada

CH-J Tools

Busque directorios y archivos para obtener una versión de aplicación específica.

Descargar fuente ZIP
CH-J / Server Manager 1704 archivos
0.1.2-beta Añadido: · Construido:
lib.rs Añadido: Fecha no registrada 23,6 KB · 484 líneas
Código Descargar archivo
1//! CH-J Tools 0.1.2 — Rust + Tauri 2 Core.
2//!
3//! Layers: `src/api` (TypeScript CH-J API) → `commands` (Tauri commands, caller checks in
4//! `security`) → `core` (services). See `docs/architecture-0.1.1.md`.
6pub mod bootstrap;
7pub mod commands;
8pub mod core;
9pub mod dialogs;
10pub mod protocol;
11pub mod security;
12pub mod windows;
14use crate::commands::license::LicenseSlot;
15use crate::core::app::CoreSlot;
16use crate::core::modules::service::DETACHED_LABEL_PREFIX;
17use crate::core::quick::{self as quick_action, QuickSlot};
18use crate::security::caller::{LICENSE_LABEL, MAIN_LABEL, QUICK_LABEL};
19use std::time::Duration;
20use tauri::{Manager, RunEvent, WindowEvent};
22fn focus_main(app: &tauri::AppHandle) {
23 if let Some(window) = app.get_webview_window(LICENSE_LABEL) {
24 let _ = window.show();
25 let _ = window.set_focus();
26 return;
27 }
28 if let Some(window) = app.get_window(MAIN_LABEL) {
29 let _ = window.unminimize();
30 let _ = window.show();
31 let _ = window.set_focus();
32 }
35/// A second start with `--chj-quick …` (system file-manager menu) opens the quick window in this process.
36#[cfg_attr(feature = "smoke", allow(dead_code))]
37fn second_instance(app: &tauri::AppHandle, args: Vec<String>) {
38 let Some(request) = quick_action::parse_args(&args) else { return focus_main(app) };
39 let slot = app.state::<QuickSlot>();
40 slot.set(request);
41 if app.state::<CoreSlot>().try_get().is_some() {
42 let _ = windows::open_quick_window(app);
43 }
44 // While the license flow or Core start is still running, `bootstrap::compose` opens the quick window.
47fn on_window_event(window: &tauri::Window, event: &WindowEvent) {
48 let app = window.app_handle().clone();
49 let label = window.label().to_string();
50 let core = app.state::<CoreSlot>().try_get();
51 match event {
52 WindowEvent::Destroyed => {
53 if label == LICENSE_LABEL {
54 bootstrap::license_window_closed(&app);
55 } else if label == QUICK_LABEL {
56 let slot = app.state::<QuickSlot>();
57 slot.clear();
58 // Started only for this action: end the process (and with it the unlocked vault).
59 if *slot.only_quick.lock() && app.get_window(MAIN_LABEL).is_none() {
60 app.exit(0);
61 }
62 } else if label == MAIN_LABEL {
63 if let Some(core) = &core {
64 core.services.diagnostics.stop_all();
65 core.services.modules.close_all(core);
66 }
67 if !cfg!(target_os = "macos") {
68 app.exit(0);
69 }
70 } else if label.starts_with(DETACHED_LABEL_PREFIX) {
71 // Returning a module clears this link first, so only a closed module window ends its module.
72 if let Some(core) = &core {
73 if let Some(module) = core.services.modules.module_of_window(&label) {
74 core.services.modules.on_destroyed(core, &module);
75 }
76 }
77 }
78 }
79 WindowEvent::Focused(false) if label == MAIN_LABEL || label.starts_with(DETACHED_LABEL_PREFIX) => {
80 if let Some(core) = core {
81 let app = app.clone();
82 tauri::async_runtime::spawn(async move {
83 // Ignore focus moving between our own windows or to the OS biometric prompt.
84 loop {
85 tokio::time::sleep(Duration::from_millis(250)).await;
86 if !core.services.biometrics.is_active() {
87 break;
88 }
89 }
90 let any_focused = app.windows().values().any(|w| w.is_focused().unwrap_or(false));
91 if !any_focused {
92 core.services.lock.lost_focus(&core).await;
93 }
94 });
95 }
96 }
97 WindowEvent::Resized(_) => {
98 if let Some(core) = core {
99 if label.starts_with(DETACHED_LABEL_PREFIX) {
100 if let Some(module) = core.services.modules.module_of_window(&label) {
101 core.services.modules.fit_detached(&core, &module);
102 }
103 }
104 if window.is_minimized().unwrap_or(false) {
105 if label == MAIN_LABEL {
106 core.services.modules.minimize_all(&core);
107 } else if let Some(module) = core.services.modules.module_of_window(&label).filter(|_| label.starts_with(DETACHED_LABEL_PREFIX)) {
108 let main_minimized = app.get_window(MAIN_LABEL).and_then(|m| m.is_minimized().ok()).unwrap_or(false);
109 core.services.modules.minimize_label(&core, &module, !main_minimized);
110 }
111 }
112 }
113 }
114 _ => {}
115 }
118/// Every Core command (plus the test-only `smoke_report` with the `smoke` feature).
119macro_rules! command_list {
120 ($($extra:path),*) => {
121 tauri::generate_handler![
122 $($extra,)*
123 commands::app::core_get_info,
124 commands::app::core_legal_open,
125 commands::app::core_open_external,
126 commands::app::core_config_get,
127 commands::app::core_config_update,
128 commands::app::core_i18n_languages,
129 commands::app::core_i18n_catalogs,
130 commands::app::window_control,
131 commands::app::window_is_maximized,
132 commands::app::window_activity,
133 commands::keychain::core_keychain,
134 commands::quick::quick_state,
135 commands::quick::quick_unlock,
136 commands::quick::quick_verify,
137 commands::quick::quick_verify_key,
138 commands::quick::quick_verify_keyserver,
139 commands::quick::quick_sign,
140 commands::quick::quick_open_main,
141 commands::standby::core_standby_get,
142 commands::standby::core_standby_set,
143 commands::vault::core_vault_status,
144 commands::vault::core_vault_create,
145 commands::vault::core_vault_unlock,
146 commands::vault::core_vault_lock,
147 commands::vault::core_vault_reset,
148 commands::vault::core_biometrics_status,
149 commands::vault::core_biometrics_enable,
150 commands::vault::core_biometrics_disable,
151 commands::vault::core_biometrics_unlock,
152 commands::vault::core_biometrics_auto_unlock,
153 commands::vault::core_biometrics_authenticate,
154 commands::profiles::core_profiles_list,
155 commands::profiles::core_profiles_save,
156 commands::profiles::core_profiles_delete,
157 commands::profiles::core_profiles_select_private_key,
158 commands::profiles::core_profiles_export,
159 commands::profiles::core_profiles_preview_import,
160 commands::profiles::core_profiles_commit_import,
161 commands::profiles::core_profiles_cancel_import,
162 commands::availability::core_availability_list,
163 commands::availability::core_availability_refresh,
164 commands::ssh::core_ssh_list,
165 commands::ssh::core_ssh_connect,
166 commands::ssh::core_ssh_trust_host_key,
167 commands::ssh::core_ssh_disconnect,
168 commands::ssh::core_ssh_resize,
169 commands::ssh::core_ssh_input,
170 commands::ssh::core_terminal_suggest,
171 commands::ssh::core_terminal_dictionary_get,
172 commands::ssh::core_terminal_dictionary_save,
173 commands::diagnostics::core_diagnostics_resolve,
174 commands::diagnostics::core_diagnostics_start,
175 commands::diagnostics::core_diagnostics_cancel,
176 commands::diagnostics::core_diagnostics_get,
177 commands::diagnostics::core_diagnostics_history,
178 commands::diagnostics::core_diagnostics_remove_history,
179 commands::diagnostics::core_diagnostics_export,
180 commands::diagnostics::core_diagnostics_copy,
181 commands::diagnostics::core_diagnostics_import,
182 commands::updates::core_updates_get_state,
183 commands::updates::core_updates_check,
184 commands::updates::core_updates_select,
185 commands::updates::core_updates_download,
186 commands::updates::core_updates_install,
187 commands::updates::core_updates_reveal,
188 commands::modules::core_modules_list,
189 commands::modules::core_modules_get_state,
190 commands::modules::core_modules_check_catalog,
191 commands::modules::core_modules_install,
192 commands::modules::core_modules_uninstall,
193 commands::modules::core_modules_open,
194 commands::modules::core_modules_set_area,
195 commands::modules::core_modules_detach,
196 commands::modules::core_modules_collapse,
197 commands::modules::core_modules_close,
198 commands::license::license_read,
199 commands::license::license_show,
200 commands::license::license_accept,
201 commands::license::license_decline,
202 commands::module_api::module_get_info,
203 commands::module_api::module_ui_get_language,
204 commands::module_api::module_close,
205 commands::module_api::module_window_minimize,
206 commands::module_api::module_host_state,
207 commands::module_api::module_host_detach,
208 commands::module_api::module_host_attach,
209 commands::module_api::module_sessions_list,
210 commands::module_api::module_system_metrics,
211 commands::module_api::module_system_virtual_memory,
212 commands::module_api::module_system_manage_virtual_memory,
213 commands::module_api::module_disks_inspect,
214 commands::module_api::module_disks_smart,
215 commands::module_api::module_disks_plan,
216 commands::module_api::module_disks_auto_expand,
217 commands::module_api::module_disks_cancel_plan,
218 commands::module_api::module_disks_apply,
219 commands::module_api::module_disks_jobs,
220 commands::module_api::module_disks_job_status,
221 commands::module_api::module_keys_generate,
222 commands::module_api::module_keys_state,
223 commands::module_api::module_keys_edit,
224 commands::module_api::module_keys_save_artifact,
225 commands::module_api::module_keys_save_bundle,
226 commands::module_api::module_keys_store_keychain,
227 commands::module_api::module_keychain_public_ssh,
228 commands::module_api::module_keys_save,
229 commands::module_api::module_keys_password,
230 commands::module_api::module_keys_copy_password,
231 commands::module_api::module_logs_read,
232 commands::module_api::module_users_list,
233 commands::module_api::module_users_manage,
234 commands::module_api::module_users_privileges,
235 commands::module_api::module_users_inventory,
236 commands::module_api::module_users_detail,
237 commands::module_api::module_users_keys,
238 commands::module_api::module_users_ssh_policy,
239 commands::module_api::module_users_ssh_password_off_all,
240 commands::module_api::module_apache_inspect,
241 commands::module_api::module_apache_inventory,
242 commands::module_api::module_apache_read_log,
243 commands::module_api::module_apache_probe_backends,
244 commands::module_api::module_apache_read_file,
245 commands::module_api::module_apache_backups,
246 commands::module_api::module_apache_read_backup,
247 commands::module_api::module_apache_plan_site,
248 commands::module_api::module_apache_plan_edit,
249 commands::module_api::module_apache_plan_fix,
250 commands::module_api::module_apache_save_file,
251 commands::module_api::module_apache_restore_backup,
252 commands::module_api::module_apache_create_site,
253 commands::module_api::module_apache_set_site_enabled,
254 commands::module_api::module_apache_adopt_site,
255 commands::module_api::module_apache_drop_broken_link,
256 commands::module_api::module_apache_set_module,
257 commands::module_api::module_apache_reload,
258 commands::module_api::module_network_inspect,
259 commands::module_api::module_network_pending,
260 commands::module_api::module_network_diagnose,
261 commands::module_api::module_network_plan_interface,
262 commands::module_api::module_network_plan_firewall,
263 commands::module_api::module_network_apply,
264 commands::module_api::module_network_verify,
265 commands::module_api::module_network_confirm,
266 commands::module_api::module_network_rollback,
267 commands::module_api::module_network_extend,
268 commands::module_api::module_network_transaction_log,
269 commands::module_api::module_rsync_ssh_profiles,
270 commands::module_api::module_rsync_local_probe,
271 commands::module_api::module_rsync_remote_probe,
272 commands::module_api::module_rsync_inspect,
273 commands::module_api::module_rsync_jobs,
274 commands::module_api::module_rsync_job,
275 commands::module_api::module_rsync_describe,
276 commands::module_api::module_rsync_versions,
277 commands::module_api::module_rsync_profiles,
278 commands::module_api::module_rsync_history,
279 commands::module_api::module_rsync_schedule_list,
280 commands::module_api::module_rsync_discover,
281 commands::module_api::module_rsync_schedule_log,
282 commands::module_api::module_rsync_take_handoff,
283 commands::module_api::module_rsync_preview,
284 commands::module_api::module_rsync_run,
285 commands::module_api::module_rsync_cancel,
286 commands::module_api::module_rsync_install,
287 commands::module_api::module_rsync_connect,
288 commands::module_api::module_rsync_trust_host,
289 commands::module_api::module_rsync_disconnect,
290 commands::module_api::module_rsync_save_profile,
291 commands::module_api::module_rsync_delete_profile,
292 commands::module_api::module_rsync_clear_history,
293 commands::module_api::module_rsync_prune_versions,
294 commands::module_api::module_rsync_schedule_install,
295 commands::module_api::module_rsync_schedule_start,
296 commands::module_api::module_rsync_schedule_remove,
297 commands::module_api::module_rsync_open_manager,
298 commands::module_api::module_apache_install_certbot,
299 commands::module_api::module_apache_issue_certificate,
300 commands::module_api::module_nginx_inspect,
301 commands::module_api::module_nginx_read_config,
302 commands::module_api::module_nginx_dump_config,
303 commands::module_api::module_nginx_test_config,
304 commands::module_api::module_nginx_save_config,
305 commands::module_api::module_nginx_reload,
306 commands::module_api::module_nginx_sites,
307 commands::module_api::module_nginx_plan_site,
308 commands::module_api::module_nginx_create_site,
309 commands::module_api::module_nginx_set_site_enabled,
310 commands::module_api::module_nginx_adopt_site,
311 commands::module_api::module_nginx_drop_broken_link,
312 commands::module_api::module_nginx_plan_route,
313 commands::module_api::module_nginx_apply_route,
314 commands::module_api::module_nginx_diagnose_domain,
315 commands::module_api::module_nginx_plan_edit,
316 commands::module_api::module_nginx_backups,
317 commands::module_api::module_nginx_read_backup,
318 commands::module_api::module_nginx_restore_backup,
319 commands::module_api::module_nginx_certificates,
320 commands::module_api::module_nginx_install_certbot,
321 commands::module_api::module_nginx_issue_certificate,
322 commands::module_api::module_nginx_read_log,
323 commands::module_api::module_nginx_probe_backends,
324 commands::module_api::module_files_list,
325 commands::module_api::module_files_privileges,
326 commands::module_api::module_files_read_text,
327 commands::module_api::module_files_write_text,
328 commands::module_api::module_files_save_text,
329 commands::module_api::module_files_list_recovery,
330 commands::module_api::module_files_read_recovery,
331 commands::module_api::module_files_cleanup_recovery,
332 commands::module_api::module_files_close_text,
333 commands::module_api::module_files_create_file,
334 commands::module_api::module_files_mkdir,
335 commands::module_api::module_files_rename,
336 commands::module_api::module_files_remove,
337 commands::module_api::module_files_remove_many,
338 commands::module_api::module_files_upload,
339 commands::module_api::module_files_download,
340 commands::module_api::module_files_download_many,
341 commands::module_api::module_files_download_archive,
342 commands::module_api::module_transfers_list,
343 commands::module_api::module_transfers_plan_upload,
344 commands::module_api::module_transfers_plan_download,
345 commands::module_api::module_transfers_start,
346 commands::module_api::module_transfers_pause,
347 commands::module_api::module_transfers_resume,
348 commands::module_api::module_transfers_retry,
349 commands::module_api::module_transfers_cancel,
350 commands::module_api::module_transfers_remove,
351 commands::module_api::module_transfers_settings,
352 commands::module_api::module_transfers_plan_copy,
353 commands::module_api::module_local_places,
354 commands::module_api::module_local_list,
355 commands::module_api::module_local_mkdir,
356 commands::module_api::module_local_create_file,
357 commands::module_api::module_local_rename,
358 commands::module_api::module_local_remove,
359 commands::module_api::module_hashing_algorithms,
360 commands::module_api::module_hashing_select_files,
361 commands::module_api::module_hashing_select_directory,
362 commands::module_api::module_hashing_select_manifest,
363 commands::module_api::module_hashing_select_manifest_destination,
364 commands::module_api::module_hashing_start,
365 commands::module_api::module_hashing_select_pgp_file,
366 commands::module_api::module_hashing_pgp_verify,
367 commands::module_api::module_hashing_pgp_keys,
368 commands::module_api::module_hashing_pgp_remove_key,
369 commands::module_api::module_hashing_verify,
370 commands::module_api::module_hashing_compare,
371 commands::module_api::module_hashing_generate_manifest,
372 commands::module_api::module_hashing_verify_manifest,
373 commands::module_api::module_hashing_export_results,
374 commands::module_api::module_hashing_copy_result,
375 commands::module_api::module_hashing_status,
376 commands::module_api::module_hashing_cancel,
377 ]
378 };
381#[cfg(not(feature = "smoke"))]
382fn command_handler() -> impl Fn(tauri::ipc::Invoke) -> bool + Send + Sync + 'static {
383 command_list!()
386#[cfg(feature = "smoke")]
387fn command_handler() -> impl Fn(tauri::ipc::Invoke) -> bool + Send + Sync + 'static {
388 command_list!(commands::smoke::smoke_report, commands::smoke::smoke_snapshot)
391/// WebKitGTK compositing keeps a software GL scene per window. The app has no animated content, and without it
392/// measured memory halves and terminal CPU falls to a quarter. Must run before the first thread and WebView start.
393#[cfg(target_os = "linux")]
394fn tune_webkit() {
395 if std::env::var_os("WEBKIT_DISABLE_COMPOSITING_MODE").is_none() {
396 std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
397 }
400/// Decides whether the app survives closing its last window. `license` is the state of the open license flow
401/// (`None` once it ended, otherwise whether it was accepted). The window system may report the last window as
402/// closed before its `Destroyed` event ends the flow, so an accepted license must count even while it is open.
403fn keep_running(core_ready: bool, license: Option<bool>, macos: bool) -> bool {
404 if !core_ready && !macos {
405 return license != Some(false);
406 }
407 macos && (core_ready || license != Some(false))
410pub fn run() {
411 #[cfg(target_os = "linux")]
412 tune_webkit();
413 let quick = QuickSlot::default();
414 if let Some(request) = quick_action::parse_args(&std::env::args().collect::<Vec<_>>()) {
415 quick.set(request);
416 *quick.only_quick.lock() = true;
417 }
418 let builder = tauri::Builder::default();
419 // Smoke builds use isolated data and must run next to a developer's open instance.
420 #[cfg(not(feature = "smoke"))]
421 let builder = builder.plugin(tauri_plugin_single_instance::init(|app, args, _cwd| second_instance(app, args)));
422 let app = builder
423 .plugin(tauri_plugin_dialog::init())
424 .plugin(tauri_plugin_clipboard_manager::init())
425 .plugin(tauri_plugin_opener::init())
426 .manage(CoreSlot::default())
427 .manage(LicenseSlot::default())
428 .manage(quick)
429 .register_uri_scheme_protocol("chj-module", protocol::handle)
430 .invoke_handler(command_handler())
431 .on_window_event(on_window_event)
432 .setup(|app| {
433 bootstrap::start(app.handle());
434 Ok(())
435 })
436 .build(tauri::generate_context!())
437 .expect("error while building CH-J Tools");
439 app.run(|handle, event| match event {
440 // Closing the last window: keep running while the Core is starting (license accepted,
441 // main window not yet created) and on macOS (same as Electron `window-all-closed`).
442 RunEvent::ExitRequested { code: None, api, .. } => {
443 let core_ready = handle.state::<CoreSlot>().try_get().is_some();
444 let license = handle.state::<LicenseSlot>().0.lock().as_ref().map(|flow| flow.accepted);
445 if keep_running(core_ready, license, cfg!(target_os = "macos")) {
446 api.prevent_exit();
447 }
448 }
449 RunEvent::Exit => {
450 if let Some(core) = handle.state::<CoreSlot>().try_get() {
451 bootstrap::shutdown(&core);
452 }
453 }
454 #[cfg(target_os = "macos")]
455 RunEvent::Reopen { has_visible_windows, .. } => {
456 if !has_visible_windows {
457 if let Some(core) = handle.state::<CoreSlot>().try_get() {
458 if handle.get_window(MAIN_LABEL).is_none() {
459 *handle.state::<QuickSlot>().only_quick.lock() = false;
460 let _ = windows::create_main_window(handle, &core.i18n, &core.config.language());
461 } else {
462 focus_main(handle);
463 }
464 }
465 }
466 }
467 _ => {}
468 });
471#[cfg(test)]
472mod last_window_tests {
473 use super::keep_running;
475 #[test]
476 fn accepted_license_keeps_the_app_until_the_main_window_opens() {
477 assert!(keep_running(false, Some(true), false), "accepted, flow still open");
478 assert!(keep_running(false, None, false), "accepted, flow ended");
479 assert!(!keep_running(false, Some(false), false), "license window closed without accepting");
480 assert!(!keep_running(true, None, false), "main window closed on Windows and Linux");
481 assert!(keep_running(true, None, true), "macOS keeps running without windows");
482 assert!(!keep_running(false, Some(false), true), "declined on macOS");
483 }
SHA-256fac40656010a237760d2ec7a1270d308c4b0b1fa3eae7ebfd78739369b101e01

CH-J Proprietary Software License 1.14 · La fuente se proporciona en el CH-J Proprietary Software License 1.14. Su disponibilidad no cambia los términos de la licencia ni otorga derechos adicionales.

Archivo SHA-256ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f
Archivos