Sorgente pubblicata
Scarica sorgente ZIP
CH-J Tools
Sfoglia directory e file per una specifica release di applicazioni.
CH-J / Server Manager
1704 file
0.1.2-beta
Aggiunto: · Costruito:
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 in4
//! `security`) → `core` (services). See `docs/architecture-0.1.1.md`.6
pub mod bootstrap;7
pub mod commands;8
pub mod core;9
pub mod dialogs;10
pub mod protocol;11
pub mod security;12
pub mod windows;14
use crate::commands::license::LicenseSlot;15
use crate::core::app::CoreSlot;16
use crate::core::modules::service::DETACHED_LABEL_PREFIX;17
use crate::core::quick::{self as quick_action, QuickSlot};18
use crate::security::caller::{LICENSE_LABEL, MAIN_LABEL, QUICK_LABEL};19
use std::time::Duration;20
use tauri::{Manager, RunEvent, WindowEvent};22
fn 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
}33
}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))]37
fn 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.45
}47
fn 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
}116
}118
/// Every Core command (plus the test-only `smoke_report` with the `smoke` feature).119
macro_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
};379
}381
#[cfg(not(feature = "smoke"))]382
fn command_handler() -> impl Fn(tauri::ipc::Invoke) -> bool + Send + Sync + 'static {383
command_list!()384
}386
#[cfg(feature = "smoke")]387
fn command_handler() -> impl Fn(tauri::ipc::Invoke) -> bool + Send + Sync + 'static {388
command_list!(commands::smoke::smoke_report, commands::smoke::smoke_snapshot)389
}391
/// WebKitGTK compositing keeps a software GL scene per window. The app has no animated content, and without it392
/// measured memory halves and terminal CPU falls to a quarter. Must run before the first thread and WebView start.393
#[cfg(target_os = "linux")]394
fn 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
}398
}400
/// Decides whether the app survives closing its last window. `license` is the state of the open license flow401
/// (`None` once it ended, otherwise whether it was accepted). The window system may report the last window as402
/// closed before its `Destroyed` event ends the flow, so an accepted license must count even while it is open.403
fn 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))408
}410
pub 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 = builder423
.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
});469
}471
#[cfg(test)]472
mod 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
}484
}SHA-256
fac40656010a237760d2ec7a1270d308c4b0b1fa3eae7ebfd78739369b101e01CH-J Proprietary Software License 1.14 · La sorgente è fornita sotto CH-J Proprietary Software License 1.14. La sua disponibilità non modifica i termini di licenza o concede diritti aggiuntivi.
Archivio SHA-256
ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f