mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
translate backend strings
This commit is contained in:
65
core/Cargo.lock
generated
65
core/Cargo.lock
generated
@@ -1177,9 +1177,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.52"
|
||||
version = "1.2.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
|
||||
checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@@ -2726,9 +2726,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
|
||||
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
|
||||
|
||||
[[package]]
|
||||
name = "fixed-capacity-vec"
|
||||
@@ -4186,9 +4186,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.83"
|
||||
version = "0.3.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
|
||||
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -6587,7 +6587,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rpc-toolkit"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/Start9Labs/rpc-toolkit.git#406ee9e88bf20e3155f150eb755b5b9c2aefd167"
|
||||
source = "git+https://github.com/Start9Labs/rpc-toolkit.git#39e547ff99d997c19f9b6483b28a4394ca5a07bc"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
@@ -6727,9 +6727,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
@@ -6806,7 +6806,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.103.8",
|
||||
"rustls-webpki 0.103.9",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -6834,9 +6834,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.13.2"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282"
|
||||
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
|
||||
dependencies = [
|
||||
"web-time",
|
||||
"zeroize",
|
||||
@@ -6856,7 +6856,7 @@ dependencies = [
|
||||
"rustls 0.23.36",
|
||||
"rustls-native-certs",
|
||||
"rustls-platform-verifier-android",
|
||||
"rustls-webpki 0.103.8",
|
||||
"rustls-webpki 0.103.9",
|
||||
"security-framework 3.5.1",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
@@ -6882,9 +6882,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.8"
|
||||
version = "0.103.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
||||
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
@@ -9556,7 +9556,7 @@ dependencies = [
|
||||
"paste",
|
||||
"pin-project",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.103.8",
|
||||
"rustls-webpki 0.103.9",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -10201,9 +10201,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
version = "1.0.2+wasi-0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
@@ -10225,9 +10225,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.106"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
||||
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -10238,11 +10238,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.56"
|
||||
version = "0.4.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c"
|
||||
checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -10251,9 +10252,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.106"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
||||
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -10261,9 +10262,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.106"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
||||
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
@@ -10274,9 +10275,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.106"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
||||
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -10375,9 +10376,9 @@ checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.83"
|
||||
version = "0.3.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac"
|
||||
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -10974,9 +10975,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
|
||||
4096
core/locales/i18n.yaml
Normal file
4096
core/locales/i18n.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
|
||||
"get-input",
|
||||
from_fn_async(get_action_input)
|
||||
.with_display_serializable()
|
||||
.with_about("Get action input spec")
|
||||
.with_about("about.get-action-input-spec")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -36,14 +36,14 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Run service action")
|
||||
.with_about("about.run-service-action")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"clear-task",
|
||||
from_fn_async(clear_task)
|
||||
.no_display()
|
||||
.with_about("Clear a service task")
|
||||
.with_about("about.clear-service-task")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,10 @@ pub async fn write_shadow(password: &str) -> Result<(), Error> {
|
||||
match line.split_once(":") {
|
||||
Some((user, rest)) if user == "start9" || user == "kiosk" => {
|
||||
let (_, rest) = rest.split_once(":").ok_or_else(|| {
|
||||
Error::new(eyre!("malformed /etc/shadow"), ErrorKind::ParseSysInfo)
|
||||
Error::new(
|
||||
eyre!("{}", t!("auth.malformed-etc-shadow")),
|
||||
ErrorKind::ParseSysInfo,
|
||||
)
|
||||
})?;
|
||||
shadow_file
|
||||
.write_all(format!("{user}:{hash}:{rest}\n").as_bytes())
|
||||
@@ -81,7 +84,7 @@ impl PasswordType {
|
||||
PasswordType::String(x) => Ok(x),
|
||||
PasswordType::EncryptedWire(x) => x.decrypt(current_secret).ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Couldn't decode password"),
|
||||
color_eyre::eyre::eyre!("{}", t!("auth.couldnt-decode-password")),
|
||||
crate::ErrorKind::Unknown,
|
||||
)
|
||||
}),
|
||||
@@ -125,19 +128,19 @@ where
|
||||
"login",
|
||||
from_fn_async(cli_login::<AC>)
|
||||
.no_display()
|
||||
.with_about("Log in a new auth session"),
|
||||
.with_about("about.login-new-auth-session"),
|
||||
)
|
||||
.subcommand(
|
||||
"logout",
|
||||
from_fn_async(logout::<AC>)
|
||||
.with_metadata("get_session", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Log out of current auth session")
|
||||
.with_about("about.logout-current-auth-session")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"session",
|
||||
session::<C, AC>().with_about("List or kill auth sessions"),
|
||||
session::<C, AC>().with_about("about.list-or-kill-auth-sessions"),
|
||||
)
|
||||
.subcommand(
|
||||
"reset-password",
|
||||
@@ -147,14 +150,14 @@ where
|
||||
"reset-password",
|
||||
from_fn_async(cli_reset_password)
|
||||
.no_display()
|
||||
.with_about("Reset password"),
|
||||
.with_about("about.reset-password"),
|
||||
)
|
||||
.subcommand(
|
||||
"get-pubkey",
|
||||
from_fn_async(get_pubkey)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.no_display()
|
||||
.with_about("Get public key derived from server private key")
|
||||
.with_about("about.get-pubkey-from-server")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -208,12 +211,12 @@ pub fn check_password(hash: &str, password: &str) -> Result<(), Error> {
|
||||
ensure_code!(
|
||||
argon2::verify_encoded(&hash, password.as_bytes()).map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("Password Incorrect"),
|
||||
eyre!("{}", t!("auth.password-incorrect")),
|
||||
crate::ErrorKind::IncorrectPassword,
|
||||
)
|
||||
})?,
|
||||
crate::ErrorKind::IncorrectPassword,
|
||||
"Password Incorrect"
|
||||
t!("auth.password-incorrect")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -327,14 +330,14 @@ where
|
||||
.with_metadata("get_session", Value::Bool(true))
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_sessions(handle.params, result))
|
||||
.with_about("Display all auth sessions")
|
||||
.with_about("about.display-all-auth-sessions")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"kill",
|
||||
from_fn_async(kill::<AC>)
|
||||
.no_display()
|
||||
.with_about("Terminate existing auth session(s)")
|
||||
.with_about("about.terminate-auth-sessions")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -447,13 +450,13 @@ async fn cli_reset_password(
|
||||
..
|
||||
}: HandlerArgs<CliContext>,
|
||||
) -> Result<(), RpcError> {
|
||||
let old_password = rpassword::prompt_password("Current Password: ")?;
|
||||
let old_password = rpassword::prompt_password(&t!("auth.prompt-current-password"))?;
|
||||
|
||||
let new_password = {
|
||||
let new_password = rpassword::prompt_password("New Password: ")?;
|
||||
if new_password != rpassword::prompt_password("Confirm: ")? {
|
||||
let new_password = rpassword::prompt_password(&t!("auth.prompt-new-password"))?;
|
||||
if new_password != rpassword::prompt_password(&t!("auth.prompt-confirm"))? {
|
||||
return Err(Error::new(
|
||||
eyre!("Passwords do not match"),
|
||||
eyre!("{}", t!("auth.passwords-do-not-match")),
|
||||
crate::ErrorKind::IncorrectPassword,
|
||||
)
|
||||
.into());
|
||||
@@ -486,7 +489,7 @@ pub async fn reset_password_impl(
|
||||
.with_kind(crate::ErrorKind::IncorrectPassword)?
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("Incorrect Password"),
|
||||
eyre!("{}", t!("auth.password-incorrect")),
|
||||
crate::ErrorKind::IncorrectPassword,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ impl BackupStatusGuard {
|
||||
db,
|
||||
None,
|
||||
NotificationLevel::Success,
|
||||
"Backup Complete".to_owned(),
|
||||
"Your backup has completed".to_owned(),
|
||||
t!("backup.bulk.complete-title").to_string(),
|
||||
t!("backup.bulk.complete-message").to_string(),
|
||||
BackupReport {
|
||||
server: ServerBackupReport {
|
||||
attempted: true,
|
||||
@@ -88,9 +88,8 @@ impl BackupStatusGuard {
|
||||
db,
|
||||
None,
|
||||
NotificationLevel::Warning,
|
||||
"Backup Complete".to_owned(),
|
||||
"Your backup has completed, but some package(s) failed to backup"
|
||||
.to_owned(),
|
||||
t!("backup.bulk.complete-title").to_string(),
|
||||
t!("backup.bulk.complete-with-failures").to_string(),
|
||||
BackupReport {
|
||||
server: ServerBackupReport {
|
||||
attempted: true,
|
||||
@@ -103,7 +102,7 @@ impl BackupStatusGuard {
|
||||
.await
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Backup Failed: {}", e);
|
||||
tracing::error!("{}", t!("backup.bulk.failed-error", error = e));
|
||||
tracing::debug!("{:?}", e);
|
||||
let err_string = e.to_string();
|
||||
db.mutate(|db| {
|
||||
@@ -111,8 +110,8 @@ impl BackupStatusGuard {
|
||||
db,
|
||||
None,
|
||||
NotificationLevel::Error,
|
||||
"Backup Failed".to_owned(),
|
||||
"Your backup failed to complete.".to_owned(),
|
||||
t!("backup.bulk.failed-title").to_string(),
|
||||
t!("backup.bulk.failed-message").to_string(),
|
||||
BackupReport {
|
||||
server: ServerBackupReport {
|
||||
attempted: true,
|
||||
@@ -224,7 +223,7 @@ fn assure_backing_up<'a>(
|
||||
.as_backup_progress_mut();
|
||||
if backing_up.transpose_ref().is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("Server is already backing up!"),
|
||||
eyre!("{}", t!("backup.bulk.already-backing-up")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -303,7 +302,7 @@ async fn perform_backup(
|
||||
|
||||
let mut backup_guard = Arc::try_unwrap(backup_guard).map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("leaked reference to BackupMountGuard"),
|
||||
eyre!("{}", t!("backup.bulk.leaked-reference")),
|
||||
ErrorKind::Incoherent,
|
||||
)
|
||||
})?;
|
||||
|
||||
@@ -37,12 +37,12 @@ pub fn backup<C: Context>() -> ParentHandler<C> {
|
||||
"create",
|
||||
from_fn_async(backup_bulk::backup_all)
|
||||
.no_display()
|
||||
.with_about("Create backup for all packages")
|
||||
.with_about("about.create-backup-all-packages")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"target",
|
||||
target::target::<C>().with_about("Commands related to a backup target"),
|
||||
target::target::<C>().with_about("about.commands-backup-target"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ pub fn package_backup<C: Context>() -> ParentHandler<C> {
|
||||
"restore",
|
||||
from_fn_async(restore::restore_packages_rpc)
|
||||
.no_display()
|
||||
.with_about("Restore package(s) from backup")
|
||||
.with_about("about.restore-packages-from-backup")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ pub async fn restore_packages_rpc(
|
||||
match async { res.await?.await }.await {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
tracing::error!("Error restoring package {}: {}", id, err);
|
||||
tracing::error!("{}", t!("backup.restore.package-error", id = id, error = err));
|
||||
tracing::debug!("{:?}", err);
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ pub async fn recover_full_server(
|
||||
match async { res.await?.await }.await {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
tracing::error!("Error restoring package {}: {}", id, err);
|
||||
tracing::error!("{}", t!("backup.restore.package-error", id = id, error = err));
|
||||
tracing::debug!("{:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,21 +52,21 @@ pub fn cifs<C: Context>() -> ParentHandler<C> {
|
||||
"add",
|
||||
from_fn_async(add)
|
||||
.no_display()
|
||||
.with_about("Add a new backup target")
|
||||
.with_about("about.add-new-backup-target")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"update",
|
||||
from_fn_async(update)
|
||||
.no_display()
|
||||
.with_about("Update an existing backup target")
|
||||
.with_about("about.update-existing-backup-target")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove)
|
||||
.no_display()
|
||||
.with_about("Remove an existing backup target")
|
||||
.with_about("about.remove-existing-backup-target")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ pub async fn update(
|
||||
id
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
eyre!("Backup Target ID {} Not Found", id),
|
||||
eyre!("{}", t!("backup.target.cifs.target-not-found", id = id)),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
};
|
||||
@@ -171,7 +171,7 @@ pub async fn update(
|
||||
.as_idx_mut(&id)
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("Backup Target ID {} Not Found", BackupTargetId::Cifs { id }),
|
||||
eyre!("{}", t!("backup.target.cifs.target-not-found", id = BackupTargetId::Cifs { id })),
|
||||
ErrorKind::NotFound,
|
||||
)
|
||||
})?
|
||||
@@ -203,7 +203,7 @@ pub async fn remove(ctx: RpcContext, RemoveParams { id }: RemoveParams) -> Resul
|
||||
id
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
eyre!("Backup Target ID {} Not Found", id),
|
||||
eyre!("{}", t!("backup.target.cifs.target-not-found", id = id)),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
};
|
||||
@@ -220,7 +220,7 @@ pub fn load(db: &DatabaseModel, id: u32) -> Result<Cifs, Error> {
|
||||
.as_idx(&id)
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("Backup Target ID {} Not Found", id),
|
||||
eyre!("{}", t!("backup.target.cifs.target-not-found-id", id = id)),
|
||||
ErrorKind::NotFound,
|
||||
)
|
||||
})?
|
||||
|
||||
@@ -143,13 +143,13 @@ pub fn target<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"cifs",
|
||||
cifs::cifs::<C>().with_about("Add, remove, or update a backup target"),
|
||||
cifs::cifs::<C>().with_about("about.add-remove-update-backup-target"),
|
||||
)
|
||||
.subcommand(
|
||||
"list",
|
||||
from_fn_async(list)
|
||||
.with_display_serializable()
|
||||
.with_about("List existing backup targets")
|
||||
.with_about("about.list-existing-backup-targets")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -159,20 +159,20 @@ pub fn target<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn::<CliContext, _>(|params, info| {
|
||||
display_backup_info(params.params, info)
|
||||
})
|
||||
.with_about("Display package backup information")
|
||||
.with_about("about.display-package-backup-information")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"mount",
|
||||
from_fn_async(mount)
|
||||
.with_about("Mount backup target")
|
||||
.with_about("about.mount-backup-target")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"umount",
|
||||
from_fn_async(umount)
|
||||
.no_display()
|
||||
.with_about("Unmount backup target")
|
||||
.with_about("about.unmount-backup-target")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub fn main(args: impl IntoIterator<Item = OsString>) {
|
||||
|cfg: ContainerClientConfig| Ok(ContainerCliContext::init(cfg)),
|
||||
crate::service::effects::handler(),
|
||||
)
|
||||
.mutate_command(super::translate_cli)
|
||||
.run(args)
|
||||
{
|
||||
match e.data {
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
use rust_i18n::t;
|
||||
|
||||
pub fn renamed(old: &str, new: &str) -> ! {
|
||||
eprintln!("{old} has been renamed to {new}");
|
||||
eprintln!(
|
||||
"{}",
|
||||
t!("bins.deprecated.renamed", old = old, new = new)
|
||||
);
|
||||
std::process::exit(1)
|
||||
}
|
||||
|
||||
pub fn removed(name: &str) -> ! {
|
||||
eprintln!("{name} has been removed");
|
||||
eprintln!("{}", t!("bins.deprecated.removed", name = name));
|
||||
std::process::exit(1)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::collections::{BTreeMap, VecDeque};
|
||||
use std::ffi::OsString;
|
||||
use std::path::Path;
|
||||
|
||||
use rust_i18n::t;
|
||||
|
||||
pub mod container_cli;
|
||||
pub mod deprecated;
|
||||
pub mod registry;
|
||||
@@ -10,6 +12,72 @@ pub mod start_init;
|
||||
pub mod startd;
|
||||
pub mod tunnel;
|
||||
|
||||
pub fn set_locale() {
|
||||
let lang = std::env::var("LANG").ok();
|
||||
let lang = lang
|
||||
.as_deref()
|
||||
.map_or("C", |l| l.strip_suffix(".UTF-8").unwrap_or(l));
|
||||
let mut set_lang = lang;
|
||||
for l in rust_i18n::available_locales!() {
|
||||
if l == lang {
|
||||
set_lang = l;
|
||||
break;
|
||||
}
|
||||
if l.split("_").next().unwrap() == lang.split("_").next().unwrap() {
|
||||
set_lang = l;
|
||||
}
|
||||
}
|
||||
rust_i18n::set_locale(set_lang);
|
||||
}
|
||||
|
||||
pub fn translate_cli(mut cmd: clap::Command) -> clap::Command {
|
||||
fn translate(s: impl std::fmt::Display) -> String {
|
||||
t!(s.to_string()).into_owned()
|
||||
}
|
||||
if let Some(s) = cmd.get_about() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.about(s);
|
||||
}
|
||||
if let Some(s) = cmd.get_long_about() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.long_about(s);
|
||||
}
|
||||
if let Some(s) = cmd.get_before_help() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.before_help(s);
|
||||
}
|
||||
if let Some(s) = cmd.get_before_long_help() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.before_long_help(s);
|
||||
}
|
||||
if let Some(s) = cmd.get_after_help() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.after_help(s);
|
||||
}
|
||||
if let Some(s) = cmd.get_after_long_help() {
|
||||
let s = translate(s);
|
||||
cmd = cmd.after_long_help(s);
|
||||
}
|
||||
|
||||
let args = cmd.get_arguments().cloned().collect::<Vec<_>>();
|
||||
for mut arg in args {
|
||||
if let Some(s) = arg.get_help() {
|
||||
let s = translate(s);
|
||||
arg = arg.help(s);
|
||||
}
|
||||
if let Some(s) = arg.get_long_help() {
|
||||
let s = translate(s);
|
||||
arg = arg.long_help(s);
|
||||
}
|
||||
cmd = cmd.arg(arg);
|
||||
}
|
||||
for cmd in cmd.get_subcommands_mut() {
|
||||
*cmd = translate_cli(cmd.clone());
|
||||
}
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MultiExecutable {
|
||||
default: Option<&'static str>,
|
||||
@@ -58,7 +126,7 @@ impl MultiExecutable {
|
||||
if let Some((name, _)) = self.bins.get_key_value(name) {
|
||||
self.default = Some(*name);
|
||||
} else {
|
||||
panic!("{name} does not exist in MultiExecutable");
|
||||
panic!("{}", t!("bins.mod.does-not-exist", name = name));
|
||||
}
|
||||
self
|
||||
}
|
||||
@@ -68,6 +136,8 @@ impl MultiExecutable {
|
||||
}
|
||||
|
||||
pub fn execute(&self) {
|
||||
set_locale();
|
||||
|
||||
let mut popped = Vec::with_capacity(2);
|
||||
let mut args = std::env::args_os().collect::<VecDeque<_>>();
|
||||
|
||||
@@ -96,11 +166,15 @@ impl MultiExecutable {
|
||||
}
|
||||
let args = std::env::args().collect::<VecDeque<_>>();
|
||||
eprintln!(
|
||||
"unknown executable: {}",
|
||||
args.get(1)
|
||||
.or_else(|| args.get(0))
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("N/A")
|
||||
"{}",
|
||||
t!(
|
||||
"bins.mod.unknown-executable",
|
||||
name = args
|
||||
.get(1)
|
||||
.or_else(|| args.get(0))
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("N/A")
|
||||
)
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::ffi::OsString;
|
||||
use clap::Parser;
|
||||
use futures::FutureExt;
|
||||
use rpc_toolkit::CliApp;
|
||||
use rust_i18n::t;
|
||||
use tokio::signal::unix::signal;
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -77,7 +78,7 @@ pub fn main(args: impl IntoIterator<Item = OsString>) {
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("failed to initialize runtime");
|
||||
.expect(&t!("bins.registry.failed-to-initialize-runtime"));
|
||||
rt.block_on(inner_main(&config))
|
||||
};
|
||||
|
||||
@@ -99,6 +100,7 @@ pub fn cli(args: impl IntoIterator<Item = OsString>) {
|
||||
|cfg: ClientConfig| Ok(CliContext::init(cfg.load()?)?),
|
||||
crate::registry::registry_api(),
|
||||
)
|
||||
.mutate_command(super::translate_cli)
|
||||
.run(args)
|
||||
{
|
||||
match e.data {
|
||||
|
||||
@@ -19,6 +19,7 @@ pub fn main(args: impl IntoIterator<Item = OsString>) {
|
||||
|cfg: ClientConfig| Ok(CliContext::init(cfg.load()?)?),
|
||||
crate::main_api(),
|
||||
)
|
||||
.mutate_command(super::translate_cli)
|
||||
.run(args)
|
||||
{
|
||||
match e.data {
|
||||
|
||||
@@ -25,7 +25,13 @@ async fn setup_or_init(
|
||||
if let Some(firmware) = check_for_firmware_update()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("Error checking for firmware update: {e}");
|
||||
tracing::warn!(
|
||||
"{}",
|
||||
t!(
|
||||
"bins.start-init.error-checking-firmware",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
})
|
||||
.ok()
|
||||
@@ -33,14 +39,21 @@ async fn setup_or_init(
|
||||
{
|
||||
let init_ctx = InitContext::init(config).await?;
|
||||
let handle = &init_ctx.progress;
|
||||
let mut update_phase = handle.add_phase("Updating Firmware".into(), Some(10));
|
||||
let mut reboot_phase = handle.add_phase("Rebooting".into(), Some(1));
|
||||
let mut update_phase =
|
||||
handle.add_phase(t!("bins.start-init.updating-firmware").into(), Some(10));
|
||||
let mut reboot_phase = handle.add_phase(t!("bins.start-init.rebooting").into(), Some(1));
|
||||
|
||||
server.serve_ui_for(init_ctx);
|
||||
|
||||
update_phase.start();
|
||||
if let Err(e) = update_firmware(firmware).await {
|
||||
tracing::warn!("Error performing firmware update: {e}");
|
||||
tracing::warn!(
|
||||
"{}",
|
||||
t!(
|
||||
"bins.start-init.error-firmware-update",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
} else {
|
||||
update_phase.complete();
|
||||
@@ -96,7 +109,13 @@ async fn setup_or_init(
|
||||
.invoke(ErrorKind::NotFound)
|
||||
.await
|
||||
{
|
||||
tracing::error!("Failed to kill kiosk: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"bins.start-init.failed-to-kill-kiosk",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
|
||||
@@ -105,7 +124,7 @@ async fn setup_or_init(
|
||||
Some(Err(e)) => return Err(e.clone_output()),
|
||||
None => {
|
||||
return Err(Error::new(
|
||||
eyre!("Setup mode exited before setup completed"),
|
||||
eyre!("{}", t!("bins.start-init.setup-mode-exited")),
|
||||
ErrorKind::Unknown,
|
||||
));
|
||||
}
|
||||
@@ -115,7 +134,8 @@ async fn setup_or_init(
|
||||
let handle = init_ctx.progress.clone();
|
||||
let err_channel = init_ctx.error.clone();
|
||||
|
||||
let mut disk_phase = handle.add_phase("Opening data drive".into(), Some(10));
|
||||
let mut disk_phase =
|
||||
handle.add_phase(t!("bins.start-init.opening-data-drive").into(), Some(10));
|
||||
let init_phases = InitPhases::new(&handle);
|
||||
let rpc_ctx_phases = InitRpcContextPhases::new(&handle);
|
||||
|
||||
@@ -147,11 +167,12 @@ async fn setup_or_init(
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, REPAIR_DISK_PATH))?;
|
||||
}
|
||||
disk_phase.complete();
|
||||
tracing::info!("Loaded Disk");
|
||||
tracing::info!("{}", t!("bins.start-init.loaded-disk"));
|
||||
|
||||
if requires_reboot.0 {
|
||||
tracing::info!("Rebooting...");
|
||||
let mut reboot_phase = handle.add_phase("Rebooting".into(), Some(1));
|
||||
tracing::info!("{}", t!("bins.start-init.rebooting"));
|
||||
let mut reboot_phase =
|
||||
handle.add_phase(t!("bins.start-init.rebooting").into(), Some(1));
|
||||
reboot_phase.start();
|
||||
return Ok(Err(Shutdown {
|
||||
disk_guid: Some(disk_guid),
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::time::Duration;
|
||||
|
||||
use clap::Parser;
|
||||
use color_eyre::eyre::eyre;
|
||||
use rust_i18n::t;
|
||||
use futures::{FutureExt, TryFutureExt};
|
||||
use tokio::signal::unix::signal;
|
||||
use tracing::instrument;
|
||||
@@ -112,11 +113,11 @@ async fn inner_main(
|
||||
metrics_task
|
||||
.map_err(|e| {
|
||||
Error::new(
|
||||
eyre!("{}", e).wrap_err("Metrics daemon panicked!"),
|
||||
eyre!("{}", e).wrap_err(t!("bins.startd.metrics-daemon-panicked").to_string()),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
})
|
||||
.map_ok(|_| tracing::debug!("Metrics daemon Shutdown"))
|
||||
.map_ok(|_| tracing::debug!("{}", t!("bins.startd.metrics-daemon-shutdown")))
|
||||
.await?;
|
||||
|
||||
let shutdown = shutdown_recv
|
||||
@@ -144,7 +145,7 @@ pub fn main(args: impl IntoIterator<Item = OsString>) {
|
||||
.worker_threads(max(1, num_cpus::get()))
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("failed to initialize runtime");
|
||||
.expect(&t!("bins.startd.failed-to-initialize-runtime"));
|
||||
let res = rt.block_on(async {
|
||||
let mut server = WebServer::new(
|
||||
Acceptor::bind_upgradable(SelfContainedNetworkInterfaceListener::bind(BindTcp, 80)),
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::time::Duration;
|
||||
use clap::Parser;
|
||||
use futures::FutureExt;
|
||||
use rpc_toolkit::CliApp;
|
||||
use rust_i18n::t;
|
||||
use tokio::signal::unix::signal;
|
||||
use tracing::instrument;
|
||||
use visit_rs::Visit;
|
||||
@@ -70,7 +71,7 @@ async fn inner_main(config: &TunnelConfig) -> Result<(), Error> {
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("error adding ssl listener: {e}");
|
||||
tracing::error!("{}", t!("bins.tunnel.error-adding-ssl-listener", error = e.to_string()));
|
||||
tracing::debug!("{e:?}");
|
||||
|
||||
false
|
||||
@@ -92,7 +93,7 @@ async fn inner_main(config: &TunnelConfig) -> Result<(), Error> {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("error updating webserver bind: {e}");
|
||||
tracing::error!("{}", t!("bins.tunnel.error-updating-webserver-bind", error = e.to_string()));
|
||||
tracing::debug!("{e:?}");
|
||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
}
|
||||
@@ -157,7 +158,7 @@ pub fn main(args: impl IntoIterator<Item = OsString>) {
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("failed to initialize runtime");
|
||||
.expect(&t!("bins.tunnel.failed-to-initialize-runtime"));
|
||||
rt.block_on(inner_main(&config))
|
||||
};
|
||||
|
||||
@@ -179,6 +180,7 @@ pub fn cli(args: impl IntoIterator<Item = OsString>) {
|
||||
|cfg: ClientConfig| Ok(CliContext::init(cfg.load()?)?),
|
||||
crate::tunnel::api::tunnel_api(),
|
||||
)
|
||||
.mutate_command(super::translate_cli)
|
||||
.run(args)
|
||||
{
|
||||
match e.data {
|
||||
|
||||
@@ -166,14 +166,14 @@ impl CliContext {
|
||||
.with_kind(crate::ErrorKind::Pem)?;
|
||||
let secret = ed25519_dalek::SecretKey::try_from(&pair.secret_key[..]).map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("pkcs8 key is of incorrect length"),
|
||||
eyre!("{}", t!("context.cli.pkcs8-key-incorrect-length")),
|
||||
ErrorKind::OpenSsl,
|
||||
)
|
||||
})?;
|
||||
return Ok(secret.into())
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Developer Key does not exist! Please run `start-cli init-key` before running this command."),
|
||||
eyre!("{}", t!("context.cli.developer-key-does-not-exist")),
|
||||
crate::ErrorKind::Uninitialized
|
||||
))
|
||||
})
|
||||
@@ -189,14 +189,14 @@ impl CliContext {
|
||||
"http" => "ws",
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
eyre!("Cannot parse scheme from base URL"),
|
||||
eyre!("{}", t!("context.cli.cannot-parse-scheme-from-base-url")),
|
||||
crate::ErrorKind::ParseUrl,
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
url.set_scheme(ws_scheme)
|
||||
.map_err(|_| Error::new(eyre!("Cannot set URL scheme"), crate::ErrorKind::ParseUrl))?;
|
||||
.map_err(|_| Error::new(eyre!("{}", t!("context.cli.cannot-set-url-scheme")), crate::ErrorKind::ParseUrl))?;
|
||||
url.path_segments_mut()
|
||||
.map_err(|_| eyre!("Url cannot be base"))
|
||||
.with_kind(crate::ErrorKind::ParseUrl)?
|
||||
|
||||
@@ -27,7 +27,7 @@ impl DiagnosticContext {
|
||||
disk_guid: Option<InternedString>,
|
||||
error: Error,
|
||||
) -> Result<Self, Error> {
|
||||
tracing::error!("Error: {}: Starting diagnostic UI", error);
|
||||
tracing::error!("{}", t!("context.diagnostic.starting-diagnostic-ui", error = error));
|
||||
tracing::debug!("{:?}", error);
|
||||
|
||||
let (shutdown, _) = tokio::sync::broadcast::channel(1);
|
||||
|
||||
@@ -84,7 +84,7 @@ pub struct RpcContextSeed {
|
||||
}
|
||||
impl Drop for RpcContextSeed {
|
||||
fn drop(&mut self) {
|
||||
tracing::info!("RpcContext is dropped");
|
||||
tracing::info!("{}", t!("context.rpc.rpc-context-dropped"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ impl RpcContext {
|
||||
let peek = db.peek().await;
|
||||
let account = AccountInfo::load(&peek)?;
|
||||
load_db.complete();
|
||||
tracing::info!("Opened PatchDB");
|
||||
tracing::info!("{}", t!("context.rpc.opened-patchdb"));
|
||||
|
||||
init_net_ctrl.start();
|
||||
let (net_controller, os_net_service) = if let Some(InitResult {
|
||||
@@ -172,15 +172,15 @@ impl RpcContext {
|
||||
(net_ctrl, os_net_service)
|
||||
};
|
||||
init_net_ctrl.complete();
|
||||
tracing::info!("Initialized Net Controller");
|
||||
tracing::info!("{}", t!("context.rpc.initialized-net-controller"));
|
||||
|
||||
if PLATFORM.ends_with("-nonfree") {
|
||||
if let Err(e) = Command::new("nvidia-smi")
|
||||
.invoke(ErrorKind::ParseSysInfo)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("nvidia-smi: {e}");
|
||||
tracing::info!("The above warning can be ignored if no NVIDIA card is present");
|
||||
tracing::warn!("{}", t!("context.rpc.nvidia-smi-error", error = e));
|
||||
tracing::info!("{}", t!("context.rpc.nvidia-warning-can-be-ignored"));
|
||||
} else {
|
||||
async {
|
||||
let version: InternedString = String::from_utf8(
|
||||
@@ -335,7 +335,7 @@ impl RpcContext {
|
||||
is_closed: AtomicBool::new(false),
|
||||
os_partitions: config.os_partitions.clone().ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("OS Partition Information Missing"),
|
||||
eyre!("{}", t!("context.rpc.os-partition-info-missing")),
|
||||
ErrorKind::Filesystem,
|
||||
)
|
||||
})?,
|
||||
@@ -365,9 +365,9 @@ impl RpcContext {
|
||||
current_secret: Arc::new(
|
||||
Jwk::generate_ec_key(josekit::jwk::alg::ec::EcCurve::P256).map_err(|e| {
|
||||
tracing::debug!("{:?}", e);
|
||||
tracing::error!("Couldn't generate ec key");
|
||||
tracing::error!("{}", t!("context.rpc.couldnt-generate-ec-key"));
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Couldn't generate ec key"),
|
||||
color_eyre::eyre::eyre!("{}", t!("context.rpc.couldnt-generate-ec-key")),
|
||||
crate::ErrorKind::Unknown,
|
||||
)
|
||||
})?,
|
||||
@@ -382,10 +382,10 @@ impl RpcContext {
|
||||
|
||||
let res = Self(seed.clone());
|
||||
res.cleanup_and_initialize(cleanup_init).await?;
|
||||
tracing::info!("Cleaned up transient states");
|
||||
tracing::info!("{}", t!("context.rpc.cleaned-up-transient-states"));
|
||||
|
||||
crate::version::post_init(&res, run_migrations).await?;
|
||||
tracing::info!("Completed migrations");
|
||||
tracing::info!("{}", t!("context.rpc.completed-migrations"));
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ impl RpcContext {
|
||||
self.crons.mutate(|c| std::mem::take(c));
|
||||
self.services.shutdown_all().await?;
|
||||
self.is_closed.store(true, Ordering::SeqCst);
|
||||
tracing::info!("RpcContext is shutdown");
|
||||
tracing::info!("{}", t!("context.rpc.rpc-context-shutdown"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ impl RpcContext {
|
||||
.await
|
||||
.result
|
||||
{
|
||||
tracing::error!("Error in session cleanup cron: {e}");
|
||||
tracing::error!("{}", t!("context.rpc.error-in-session-cleanup-cron", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ use crate::util::sync::SyncMutex;
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref CURRENT_SECRET: Jwk = Jwk::generate_ec_key(josekit::jwk::alg::ec::EcCurve::P256).unwrap_or_else(|e| {
|
||||
tracing::debug!("{:?}", e);
|
||||
tracing::error!("Couldn't generate ec key");
|
||||
tracing::error!("{}", t!("context.setup.couldnt-generate-ec-key"));
|
||||
panic!("Couldn't generate ec key")
|
||||
});
|
||||
}
|
||||
@@ -125,11 +125,11 @@ impl SetupContext {
|
||||
.get_or_init(|| async {
|
||||
match f().await {
|
||||
Ok(res) => {
|
||||
tracing::info!("Setup complete!");
|
||||
tracing::info!("{}", t!("context.setup.setup-complete"));
|
||||
Ok(res)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Setup failed: {e}");
|
||||
tracing::error!("{}", t!("context.setup.setup-failed", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
Err(e)
|
||||
}
|
||||
@@ -142,10 +142,10 @@ impl SetupContext {
|
||||
)
|
||||
.map_err(|_| {
|
||||
if self.result.initialized() {
|
||||
Error::new(eyre!("Setup already complete"), ErrorKind::InvalidRequest)
|
||||
Error::new(eyre!("{}", t!("context.setup.setup-already-complete")), ErrorKind::InvalidRequest)
|
||||
} else {
|
||||
Error::new(
|
||||
eyre!("Setup already in progress"),
|
||||
eyre!("{}", t!("context.setup.setup-already-in-progress")),
|
||||
ErrorKind::InvalidRequest,
|
||||
)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ impl SetupContext {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error in setup progress websocket: {e}");
|
||||
tracing::error!("{}", t!("context.setup.error-in-setup-progress-websocket", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
},
|
||||
|
||||
@@ -54,7 +54,7 @@ pub fn db<C: Context>() -> ParentHandler<C> {
|
||||
"dump",
|
||||
from_fn_async(cli_dump)
|
||||
.with_display_serializable()
|
||||
.with_about("Filter/query db to display tables and records"),
|
||||
.with_about("about.filter-query-db"),
|
||||
)
|
||||
.subcommand("dump", from_fn_async(dump).no_cli())
|
||||
.subcommand(
|
||||
@@ -65,13 +65,13 @@ pub fn db<C: Context>() -> ParentHandler<C> {
|
||||
)
|
||||
.subcommand(
|
||||
"put",
|
||||
put::<C>().with_about("Command for adding UI record to db"),
|
||||
put::<C>().with_about("about.command-add-ui-record-db"),
|
||||
)
|
||||
.subcommand(
|
||||
"apply",
|
||||
from_fn_async(cli_apply)
|
||||
.no_display()
|
||||
.with_about("Update a db record"),
|
||||
.with_about("about.update-db-record"),
|
||||
)
|
||||
.subcommand("apply", from_fn_async(apply).no_cli())
|
||||
}
|
||||
@@ -358,7 +358,7 @@ pub fn put<C: Context>() -> ParentHandler<C> {
|
||||
"ui",
|
||||
from_fn_async(ui)
|
||||
.with_display_serializable()
|
||||
.with_about("Add path and value to db")
|
||||
.with_about("about.add-path-value-db")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,45 +17,46 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"error",
|
||||
from_fn(error)
|
||||
.with_about("Display diagnostic error")
|
||||
.with_about("about.display-diagnostic-error")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
crate::system::logs::<DiagnosticContext>().with_about("Display OS logs"),
|
||||
crate::system::logs::<DiagnosticContext>().with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("Display OS logs"),
|
||||
.with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
crate::system::kernel_logs::<DiagnosticContext>().with_about("Display kernel logs"),
|
||||
crate::system::kernel_logs::<DiagnosticContext>()
|
||||
.with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("Display kernal logs"),
|
||||
.with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"restart",
|
||||
from_fn(restart)
|
||||
.no_display()
|
||||
.with_about("Restart the server")
|
||||
.with_about("about.restart-server")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"disk",
|
||||
disk::<C>().with_about("Command to remove disk from filesystem"),
|
||||
disk::<C>().with_about("about.command-remove-disk-filesystem"),
|
||||
)
|
||||
.subcommand(
|
||||
"rebuild",
|
||||
from_fn_async(rebuild)
|
||||
.no_display()
|
||||
.with_about("Teardown and rebuild service containers")
|
||||
.with_about("about.teardown-rebuild-containers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -89,7 +90,7 @@ pub fn disk<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(forget_disk::<RpcContext>).no_display(),
|
||||
)
|
||||
.no_display()
|
||||
.with_about("Remove disk from filesystem"),
|
||||
.with_about("about.remove-disk-filesystem"),
|
||||
)
|
||||
.subcommand("repair", from_fn_async(|_: C| repair()).no_cli())
|
||||
.subcommand(
|
||||
@@ -97,7 +98,7 @@ pub fn disk<C: Context>() -> ParentHandler<C> {
|
||||
CallRemoteHandler::<CliContext, _, _>::new(
|
||||
from_fn_async(|_: RpcContext| repair())
|
||||
.no_display()
|
||||
.with_about("Repair disk in the event of corruption"),
|
||||
.with_about("about.repair-disk-corruption"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::path::Path;
|
||||
use color_eyre::eyre::eyre;
|
||||
use futures::FutureExt;
|
||||
use futures::future::BoxFuture;
|
||||
use rust_i18n::t;
|
||||
use tokio::process::Command;
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -62,33 +63,31 @@ async fn e2fsck_runner(
|
||||
let e2fsck_stderr = String::from_utf8(e2fsck_out.stderr)?;
|
||||
let code = e2fsck_out.status.code().ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("e2fsck: process terminated by signal"),
|
||||
eyre!("{}", t!("disk.fsck.process-terminated-by-signal")),
|
||||
crate::ErrorKind::DiskManagement,
|
||||
)
|
||||
})?;
|
||||
if code & 4 != 0 {
|
||||
tracing::error!(
|
||||
"some filesystem errors NOT corrected on {}:\n{}",
|
||||
logicalname.as_ref().display(),
|
||||
e2fsck_stderr,
|
||||
"{}",
|
||||
t!("disk.fsck.errors-not-corrected", device = logicalname.as_ref().display(), stderr = e2fsck_stderr),
|
||||
);
|
||||
} else if code & 1 != 0 {
|
||||
tracing::warn!(
|
||||
"filesystem errors corrected on {}:\n{}",
|
||||
logicalname.as_ref().display(),
|
||||
e2fsck_stderr,
|
||||
"{}",
|
||||
t!("disk.fsck.errors-corrected", device = logicalname.as_ref().display(), stderr = e2fsck_stderr),
|
||||
);
|
||||
}
|
||||
if code < 8 {
|
||||
if code & 2 != 0 {
|
||||
tracing::warn!("reboot required");
|
||||
tracing::warn!("{}", t!("disk.fsck.reboot-required"));
|
||||
Ok(RequiresReboot(true))
|
||||
} else {
|
||||
Ok(RequiresReboot(false))
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("e2fsck: {}", e2fsck_stderr),
|
||||
eyre!("{}", t!("disk.fsck.e2fsck-error", stderr = e2fsck_stderr)),
|
||||
crate::ErrorKind::DiskManagement,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use color_eyre::eyre::eyre;
|
||||
use imbl_value::InternedString;
|
||||
use rust_i18n::t;
|
||||
use tokio::process::Command;
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -225,7 +226,7 @@ pub async fn import<P: AsRef<Path>>(
|
||||
.is_none()
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("StartOS disk not found."),
|
||||
eyre!("{}", t!("disk.main.disk-not-found")),
|
||||
crate::ErrorKind::DiskNotAvailable,
|
||||
));
|
||||
}
|
||||
@@ -235,7 +236,7 @@ pub async fn import<P: AsRef<Path>>(
|
||||
.any(|id| id == guid)
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("A StartOS disk was found, but it is not the correct disk for this device."),
|
||||
eyre!("{}", t!("disk.main.incorrect-disk")),
|
||||
crate::ErrorKind::IncorrectDisk,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ pub fn disk<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(list)
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_disk_info(handle.params, result))
|
||||
.with_about("List disk info")
|
||||
.with_about("about.list-disk-info")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand("repair", from_fn_async(|_: C| repair()).no_cli())
|
||||
@@ -60,7 +60,7 @@ pub fn disk<C: Context>() -> ParentHandler<C> {
|
||||
CallRemoteHandler::<CliContext, _, _>::new(
|
||||
from_fn_async(|_: RpcContext| repair())
|
||||
.no_display()
|
||||
.with_about("Repair disk in the event of corruption"),
|
||||
.with_about("about.repair-disk-corruption"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,9 +23,8 @@ pub async fn bind<P0: AsRef<Path>, P1: AsRef<Path>>(
|
||||
read_only: bool,
|
||||
) -> Result<(), Error> {
|
||||
tracing::info!(
|
||||
"Binding {} to {}",
|
||||
src.as_ref().display(),
|
||||
dst.as_ref().display()
|
||||
"{}",
|
||||
t!("disk.mount.binding", src = src.as_ref().display(), dst = dst.as_ref().display())
|
||||
);
|
||||
if is_mountpoint(&dst).await? {
|
||||
unmount(dst.as_ref(), true).await?;
|
||||
|
||||
@@ -95,7 +95,7 @@ pub async fn get_vendor<P: AsRef<Path>>(path: P) -> Result<Option<String>, Error
|
||||
Path::new(SYS_BLOCK_PATH)
|
||||
.join(path.as_ref().strip_prefix("/dev").map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("not a canonical block device"),
|
||||
eyre!("{}", t!("disk.util.not-canonical-block-device")),
|
||||
crate::ErrorKind::BlockDevice,
|
||||
)
|
||||
})?)
|
||||
@@ -118,7 +118,7 @@ pub async fn get_model<P: AsRef<Path>>(path: P) -> Result<Option<String>, Error>
|
||||
Path::new(SYS_BLOCK_PATH)
|
||||
.join(path.as_ref().strip_prefix("/dev").map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("not a canonical block device"),
|
||||
eyre!("{}", t!("disk.util.not-canonical-block-device")),
|
||||
crate::ErrorKind::BlockDevice,
|
||||
)
|
||||
})?)
|
||||
@@ -374,23 +374,22 @@ async fn disk_info(disk: PathBuf) -> DiskInfo {
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!(
|
||||
"Could not get partition table of {}: {}",
|
||||
disk.display(),
|
||||
e.source
|
||||
"{}",
|
||||
t!("disk.util.could-not-get-partition-table", disk = disk.display(), error = e.source)
|
||||
)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let vendor = get_vendor(&disk)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get vendor of {}: {}", disk.display(), e.source))
|
||||
.map_err(|e| tracing::warn!("{}", t!("disk.util.could-not-get-vendor", disk = disk.display(), error = e.source)))
|
||||
.unwrap_or_default();
|
||||
let model = get_model(&disk)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get model of {}: {}", disk.display(), e.source))
|
||||
.map_err(|e| tracing::warn!("{}", t!("disk.util.could-not-get-model", disk = disk.display(), error = e.source)))
|
||||
.unwrap_or_default();
|
||||
let capacity = get_capacity(&disk)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get capacity of {}: {}", disk.display(), e.source))
|
||||
.map_err(|e| tracing::warn!("{}", t!("disk.util.could-not-get-capacity", disk = disk.display(), error = e.source)))
|
||||
.unwrap_or_default();
|
||||
DiskInfo {
|
||||
logicalname: disk,
|
||||
@@ -407,21 +406,21 @@ async fn part_info(part: PathBuf) -> PartitionInfo {
|
||||
let mut start_os = BTreeMap::new();
|
||||
let label = get_label(&part)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get label of {}: {}", part.display(), e.source))
|
||||
.map_err(|e| tracing::warn!("{}", t!("disk.util.could-not-get-label", part = part.display(), error = e.source)))
|
||||
.unwrap_or_default();
|
||||
let capacity = get_capacity(&part)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get capacity of {}: {}", part.display(), e.source))
|
||||
.map_err(|e| tracing::warn!("{}", t!("disk.util.could-not-get-capacity-part", part = part.display(), error = e.source)))
|
||||
.unwrap_or_default();
|
||||
let mut used = None;
|
||||
|
||||
match TmpMountGuard::mount(&BlockDev::new(&part), ReadOnly).await {
|
||||
Err(e) => tracing::warn!("Could not collect usage information: {}", e.source),
|
||||
Err(e) => tracing::warn!("{}", t!("disk.util.could-not-collect-usage-info", error = e.source)),
|
||||
Ok(mount_guard) => {
|
||||
used = get_used(mount_guard.path())
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("Could not get usage of {}: {}", part.display(), e.source)
|
||||
tracing::warn!("{}", t!("disk.util.could-not-get-usage", part = part.display(), error = e.source))
|
||||
})
|
||||
.ok();
|
||||
match recovery_info(mount_guard.path()).await {
|
||||
@@ -429,11 +428,11 @@ async fn part_info(part: PathBuf) -> PartitionInfo {
|
||||
start_os = a;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Error fetching unencrypted backup metadata: {}", e);
|
||||
tracing::error!("{}", t!("disk.util.error-fetching-backup-metadata", error = e));
|
||||
}
|
||||
}
|
||||
if let Err(e) = mount_guard.unmount().await {
|
||||
tracing::error!("Error unmounting partition {}: {}", part.display(), e);
|
||||
tracing::error!("{}", t!("disk.util.error-unmounting-partition", part = part.display(), error = e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,7 +473,7 @@ fn parse_pvscan_output(pvscan_output: &str) -> BTreeMap<PathBuf, Option<Interned
|
||||
ret.insert(PathBuf::from(pv), vg.map(InternedString::intern));
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::warn!("Failed to parse pvscan output line: {}", entry);
|
||||
tracing::warn!("{}", t!("disk.util.failed-to-parse-pvscan", line = entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use rpc_toolkit::reqwest;
|
||||
use rpc_toolkit::yajrc::{
|
||||
INVALID_PARAMS_ERROR, INVALID_REQUEST_ERROR, METHOD_NOT_FOUND_ERROR, PARSE_ERROR, RpcError,
|
||||
};
|
||||
use rust_i18n::t;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_rustls::rustls;
|
||||
@@ -100,94 +101,94 @@ pub enum ErrorKind {
|
||||
SetSysInfo = 79,
|
||||
}
|
||||
impl ErrorKind {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
pub fn as_str(&self) -> String {
|
||||
use ErrorKind::*;
|
||||
match self {
|
||||
Unknown => "Unknown Error",
|
||||
Filesystem => "Filesystem I/O Error",
|
||||
Docker => "Docker Error",
|
||||
ConfigSpecViolation => "Config Spec Violation",
|
||||
ConfigRulesViolation => "Config Rules Violation",
|
||||
NotFound => "Not Found",
|
||||
IncorrectPassword => "Incorrect Password",
|
||||
VersionIncompatible => "Version Incompatible",
|
||||
Network => "Network Error",
|
||||
Registry => "Registry Error",
|
||||
Serialization => "Serialization Error",
|
||||
Deserialization => "Deserialization Error",
|
||||
Utf8 => "UTF-8 Parse Error",
|
||||
ParseVersion => "Version Parsing Error",
|
||||
IncorrectDisk => "Incorrect Disk",
|
||||
// Nginx => "Nginx Error",
|
||||
Dependency => "Dependency Error",
|
||||
ParseS9pk => "S9PK Parsing Error",
|
||||
ParseUrl => "URL Parsing Error",
|
||||
DiskNotAvailable => "Disk Not Available",
|
||||
BlockDevice => "Block Device Error",
|
||||
InvalidOnionAddress => "Invalid Onion Address",
|
||||
Pack => "Pack Error",
|
||||
ValidateS9pk => "S9PK Validation Error",
|
||||
DiskCorrupted => "Disk Corrupted", // Remove
|
||||
Tor => "Tor Daemon Error",
|
||||
ConfigGen => "Config Generation Error",
|
||||
ParseNumber => "Number Parsing Error",
|
||||
Database => "Database Error",
|
||||
InvalidId => "Invalid ID",
|
||||
InvalidSignature => "Invalid Signature",
|
||||
Backup => "Backup Error",
|
||||
Restore => "Restore Error",
|
||||
Authorization => "Unauthorized",
|
||||
AutoConfigure => "Auto-Configure Error",
|
||||
Action => "Action Failed",
|
||||
RateLimited => "Rate Limited",
|
||||
InvalidRequest => "Invalid Request",
|
||||
MigrationFailed => "Migration Failed",
|
||||
Uninitialized => "Uninitialized",
|
||||
ParseNetAddress => "Net Address Parsing Error",
|
||||
ParseSshKey => "SSH Key Parsing Error",
|
||||
SoundError => "Sound Interface Error",
|
||||
ParseTimestamp => "Timestamp Parsing Error",
|
||||
ParseSysInfo => "System Info Parsing Error",
|
||||
Wifi => "WiFi Internal Error",
|
||||
Journald => "Journald Error",
|
||||
DiskManagement => "Disk Management Error",
|
||||
OpenSsl => "OpenSSL Internal Error",
|
||||
PasswordHashGeneration => "Password Hash Generation Error",
|
||||
DiagnosticMode => "Server is in Diagnostic Mode",
|
||||
ParseDbField => "Database Field Parse Error",
|
||||
Duplicate => "Duplication Error",
|
||||
MultipleErrors => "Multiple Errors",
|
||||
Incoherent => "Incoherent",
|
||||
InvalidBackupTargetId => "Invalid Backup Target ID",
|
||||
ProductKeyMismatch => "Incompatible Product Keys",
|
||||
LanPortConflict => "Incompatible LAN Port Configuration",
|
||||
Javascript => "Javascript Engine Error",
|
||||
Pem => "PEM Encoding Error",
|
||||
TLSInit => "TLS Backend Initialization Error",
|
||||
Ascii => "ASCII Parse Error",
|
||||
MissingHeader => "Missing Header",
|
||||
Grub => "Grub Error",
|
||||
Systemd => "Systemd Error",
|
||||
OpenSsh => "OpenSSH Error",
|
||||
Zram => "Zram Error",
|
||||
Lshw => "LSHW Error",
|
||||
CpuSettings => "CPU Settings Error",
|
||||
Firmware => "Firmware Error",
|
||||
Timeout => "Timeout Error",
|
||||
Lxc => "LXC Error",
|
||||
Cancelled => "Cancelled",
|
||||
Git => "Git Error",
|
||||
DBus => "DBus Error",
|
||||
InstallFailed => "Install Failed",
|
||||
UpdateFailed => "Update Failed",
|
||||
Smtp => "SMTP Error",
|
||||
SetSysInfo => "Error Setting System Info",
|
||||
}
|
||||
Unknown => t!("error.unknown"),
|
||||
Filesystem => t!("error.filesystem"),
|
||||
Docker => t!("error.docker"),
|
||||
ConfigSpecViolation => t!("error.config-spec-violation"),
|
||||
ConfigRulesViolation => t!("error.config-rules-violation"),
|
||||
NotFound => t!("error.not-found"),
|
||||
IncorrectPassword => t!("error.incorrect-password"),
|
||||
VersionIncompatible => t!("error.version-incompatible"),
|
||||
Network => t!("error.network"),
|
||||
Registry => t!("error.registry"),
|
||||
Serialization => t!("error.serialization"),
|
||||
Deserialization => t!("error.deserialization"),
|
||||
Utf8 => t!("error.utf8"),
|
||||
ParseVersion => t!("error.parse-version"),
|
||||
IncorrectDisk => t!("error.incorrect-disk"),
|
||||
// Nginx => t!("error.nginx"),
|
||||
Dependency => t!("error.dependency"),
|
||||
ParseS9pk => t!("error.parse-s9pk"),
|
||||
ParseUrl => t!("error.parse-url"),
|
||||
DiskNotAvailable => t!("error.disk-not-available"),
|
||||
BlockDevice => t!("error.block-device"),
|
||||
InvalidOnionAddress => t!("error.invalid-onion-address"),
|
||||
Pack => t!("error.pack"),
|
||||
ValidateS9pk => t!("error.validate-s9pk"),
|
||||
DiskCorrupted => t!("error.disk-corrupted"), // Remove
|
||||
Tor => t!("error.tor"),
|
||||
ConfigGen => t!("error.config-gen"),
|
||||
ParseNumber => t!("error.parse-number"),
|
||||
Database => t!("error.database"),
|
||||
InvalidId => t!("error.invalid-id"),
|
||||
InvalidSignature => t!("error.invalid-signature"),
|
||||
Backup => t!("error.backup"),
|
||||
Restore => t!("error.restore"),
|
||||
Authorization => t!("error.authorization"),
|
||||
AutoConfigure => t!("error.auto-configure"),
|
||||
Action => t!("error.action"),
|
||||
RateLimited => t!("error.rate-limited"),
|
||||
InvalidRequest => t!("error.invalid-request"),
|
||||
MigrationFailed => t!("error.migration-failed"),
|
||||
Uninitialized => t!("error.uninitialized"),
|
||||
ParseNetAddress => t!("error.parse-net-address"),
|
||||
ParseSshKey => t!("error.parse-ssh-key"),
|
||||
SoundError => t!("error.sound-error"),
|
||||
ParseTimestamp => t!("error.parse-timestamp"),
|
||||
ParseSysInfo => t!("error.parse-sys-info"),
|
||||
Wifi => t!("error.wifi"),
|
||||
Journald => t!("error.journald"),
|
||||
DiskManagement => t!("error.disk-management"),
|
||||
OpenSsl => t!("error.openssl"),
|
||||
PasswordHashGeneration => t!("error.password-hash-generation"),
|
||||
DiagnosticMode => t!("error.diagnostic-mode"),
|
||||
ParseDbField => t!("error.parse-db-field"),
|
||||
Duplicate => t!("error.duplicate"),
|
||||
MultipleErrors => t!("error.multiple-errors"),
|
||||
Incoherent => t!("error.incoherent"),
|
||||
InvalidBackupTargetId => t!("error.invalid-backup-target-id"),
|
||||
ProductKeyMismatch => t!("error.product-key-mismatch"),
|
||||
LanPortConflict => t!("error.lan-port-conflict"),
|
||||
Javascript => t!("error.javascript"),
|
||||
Pem => t!("error.pem"),
|
||||
TLSInit => t!("error.tls-init"),
|
||||
Ascii => t!("error.ascii"),
|
||||
MissingHeader => t!("error.missing-header"),
|
||||
Grub => t!("error.grub"),
|
||||
Systemd => t!("error.systemd"),
|
||||
OpenSsh => t!("error.openssh"),
|
||||
Zram => t!("error.zram"),
|
||||
Lshw => t!("error.lshw"),
|
||||
CpuSettings => t!("error.cpu-settings"),
|
||||
Firmware => t!("error.firmware"),
|
||||
Timeout => t!("error.timeout"),
|
||||
Lxc => t!("error.lxc"),
|
||||
Cancelled => t!("error.cancelled"),
|
||||
Git => t!("error.git"),
|
||||
DBus => t!("error.dbus"),
|
||||
InstallFailed => t!("error.install-failed"),
|
||||
UpdateFailed => t!("error.update-failed"),
|
||||
Smtp => t!("error.smtp"),
|
||||
SetSysInfo => t!("error.set-sys-info"),
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
impl Display for ErrorKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
write!(f, "{}", &self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +202,7 @@ pub struct Error {
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}: {:#}", self.kind.as_str(), self.source)
|
||||
write!(f, "{}: {:#}", &self.kind.as_str(), self.source)
|
||||
}
|
||||
}
|
||||
impl Debug for Error {
|
||||
@@ -209,7 +210,7 @@ impl Debug for Error {
|
||||
write!(
|
||||
f,
|
||||
"{}: {:?}",
|
||||
self.kind.as_str(),
|
||||
&self.kind.as_str(),
|
||||
self.debug.as_ref().unwrap_or(&self.source)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -81,26 +81,28 @@ impl InitPhases {
|
||||
pub fn new(handle: &FullProgressTracker) -> Self {
|
||||
Self {
|
||||
preinit: if Path::new("/media/startos/config/preinit.sh").exists() {
|
||||
Some(handle.add_phase("Running preinit.sh".into(), Some(5)))
|
||||
Some(handle.add_phase(t!("init.running-preinit").into(), Some(5)))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
local_auth: handle.add_phase("Enabling local authentication".into(), Some(1)),
|
||||
load_database: handle.add_phase("Loading database".into(), Some(5)),
|
||||
load_ssh_keys: handle.add_phase("Loading SSH Keys".into(), Some(1)),
|
||||
start_net: handle.add_phase("Starting network controller".into(), Some(1)),
|
||||
mount_logs: handle.add_phase("Switching logs to write to data drive".into(), Some(1)),
|
||||
load_ca_cert: handle.add_phase("Loading CA certificate".into(), Some(1)),
|
||||
load_wifi: handle.add_phase("Loading WiFi configuration".into(), Some(1)),
|
||||
init_tmp: handle.add_phase("Initializing temporary files".into(), Some(1)),
|
||||
set_governor: handle.add_phase("Setting CPU performance profile".into(), Some(1)),
|
||||
sync_clock: handle.add_phase("Synchronizing system clock".into(), Some(10)),
|
||||
enable_zram: handle.add_phase("Enabling ZRAM".into(), Some(1)),
|
||||
update_server_info: handle.add_phase("Updating server info".into(), Some(1)),
|
||||
launch_service_network: handle.add_phase("Launching service intranet".into(), Some(1)),
|
||||
validate_db: handle.add_phase("Validating database".into(), Some(1)),
|
||||
local_auth: handle.add_phase(t!("init.enabling-local-auth").into(), Some(1)),
|
||||
load_database: handle.add_phase(t!("init.loading-database").into(), Some(5)),
|
||||
load_ssh_keys: handle.add_phase(t!("init.loading-ssh-keys").into(), Some(1)),
|
||||
start_net: handle.add_phase(t!("init.starting-network-controller").into(), Some(1)),
|
||||
mount_logs: handle.add_phase(t!("init.switching-logs-to-data-drive").into(), Some(1)),
|
||||
load_ca_cert: handle.add_phase(t!("init.loading-ca-certificate").into(), Some(1)),
|
||||
load_wifi: handle.add_phase(t!("init.loading-wifi-configuration").into(), Some(1)),
|
||||
init_tmp: handle.add_phase(t!("init.initializing-temporary-files").into(), Some(1)),
|
||||
set_governor: handle
|
||||
.add_phase(t!("init.setting-cpu-performance-profile").into(), Some(1)),
|
||||
sync_clock: handle.add_phase(t!("init.synchronizing-system-clock").into(), Some(10)),
|
||||
enable_zram: handle.add_phase(t!("init.enabling-zram").into(), Some(1)),
|
||||
update_server_info: handle.add_phase(t!("init.updating-server-info").into(), Some(1)),
|
||||
launch_service_network: handle
|
||||
.add_phase(t!("init.launching-service-intranet").into(), Some(1)),
|
||||
validate_db: handle.add_phase(t!("init.validating-database").into(), Some(1)),
|
||||
postinit: if Path::new("/media/startos/config/postinit.sh").exists() {
|
||||
Some(handle.add_phase("Running postinit.sh".into(), Some(5)))
|
||||
Some(handle.add_phase(t!("init.running-postinit").into(), Some(5)))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
@@ -127,7 +129,14 @@ pub async fn run_script<P: AsRef<Path>>(path: P, mut progress: PhaseProgressTrac
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error Running {}: {}", script.display(), e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"init.error-running-script",
|
||||
script = script.display(),
|
||||
error = e
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
progress.complete();
|
||||
@@ -230,6 +239,7 @@ pub async fn init(
|
||||
.arg("-R")
|
||||
.arg("+C")
|
||||
.arg("/var/log/journal")
|
||||
.env("LANG", "C.UTF-8")
|
||||
.invoke(ErrorKind::Filesystem)
|
||||
.await
|
||||
{
|
||||
@@ -314,14 +324,17 @@ pub async fn init(
|
||||
{
|
||||
Some(governor)
|
||||
} else {
|
||||
tracing::warn!("CPU Governor \"{governor}\" Not Available");
|
||||
tracing::warn!(
|
||||
"{}",
|
||||
t!("init.cpu-governor-not-available", governor = governor)
|
||||
);
|
||||
None
|
||||
}
|
||||
} else {
|
||||
cpupower::get_preferred_governor().await?
|
||||
};
|
||||
if let Some(governor) = governor {
|
||||
tracing::info!("Setting CPU Governor to \"{governor}\"");
|
||||
tracing::info!("{}", t!("init.setting-cpu-governor", governor = governor));
|
||||
cpupower::set_governor(governor).await?;
|
||||
}
|
||||
set_governor.complete();
|
||||
@@ -349,14 +362,14 @@ pub async fn init(
|
||||
}
|
||||
}
|
||||
if !ntp_synced {
|
||||
tracing::warn!("Timed out waiting for system time to synchronize");
|
||||
tracing::warn!("{}", t!("init.clock-sync-timeout"));
|
||||
}
|
||||
sync_clock.complete();
|
||||
|
||||
enable_zram.start();
|
||||
if server_info.as_zram().de()? {
|
||||
crate::system::enable_zram().await?;
|
||||
tracing::info!("Enabled ZRAM");
|
||||
tracing::info!("{}", t!("init.enabled-zram"));
|
||||
}
|
||||
enable_zram.complete();
|
||||
|
||||
@@ -404,7 +417,7 @@ pub async fn init(
|
||||
run_script("/media/startos/config/postinit.sh", progress).await;
|
||||
}
|
||||
|
||||
tracing::info!("System initialized.");
|
||||
tracing::info!("{}", t!("init.system-initialized"));
|
||||
|
||||
Ok(InitResult {
|
||||
net_ctrl,
|
||||
@@ -416,30 +429,30 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"logs",
|
||||
crate::system::logs::<InitContext>().with_about("Disply OS logs"),
|
||||
crate::system::logs::<InitContext>().with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("Display OS logs"),
|
||||
.with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
crate::system::kernel_logs::<InitContext>().with_about("Display kernel logs"),
|
||||
crate::system::kernel_logs::<InitContext>().with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("Display kernel logs"),
|
||||
.with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand("subscribe", from_fn_async(init_progress).no_cli())
|
||||
.subcommand(
|
||||
"subscribe",
|
||||
from_fn_async(cli_init_progress)
|
||||
.no_display()
|
||||
.with_about("Get initialization progress"),
|
||||
.with_about("about.get-initialization-progress"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -495,7 +508,7 @@ pub async fn init_progress(ctx: InitContext) -> Result<InitProgressRes, Error> {
|
||||
);
|
||||
|
||||
if let Err(e) = ws.close_result(res.map(|_| "complete")).await {
|
||||
tracing::error!("error closing init progress websocket: {e}");
|
||||
tracing::error!("{}", t!("init.error-closing-websocket", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
},
|
||||
@@ -526,7 +539,7 @@ pub async fn cli_init_progress(
|
||||
.await?,
|
||||
)?;
|
||||
let mut ws = ctx.ws_continuation(res.guid).await?;
|
||||
let mut bar = PhasedProgressBar::new("Initializing...");
|
||||
let mut bar = PhasedProgressBar::new(&t!("init.initializing"));
|
||||
while let Some(msg) = ws.try_next().await.with_kind(ErrorKind::Network)? {
|
||||
if let tokio_tungstenite::tungstenite::Message::Text(msg) = msg {
|
||||
bar.update(&serde_json::from_str(&msg).with_kind(ErrorKind::Deserialization)?);
|
||||
|
||||
170
core/src/lib.rs
170
core/src/lib.rs
@@ -135,80 +135,63 @@ pub fn main_api<C: Context>() -> ParentHandler<C> {
|
||||
let mut api = ParentHandler::new()
|
||||
.subcommand(
|
||||
"git-info",
|
||||
from_fn(|_: C| version::git_info()).with_about("Display the githash of StartOS CLI"),
|
||||
from_fn(|_: C| version::git_info()).with_about("about.display-githash"),
|
||||
)
|
||||
.subcommand(
|
||||
"echo",
|
||||
from_fn(echo::<RpcContext>)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_about("Echo a message")
|
||||
.with_about("about.echo-message")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"state",
|
||||
from_fn(|_: RpcContext| Ok::<_, Error>(ApiState::Running))
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_about("Display the API that is currently serving")
|
||||
.with_about("about.display-current-api")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"state",
|
||||
from_fn(|_: InitContext| Ok::<_, Error>(ApiState::Initializing))
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_about("Display the API that is currently serving")
|
||||
.with_about("about.display-current-api")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"state",
|
||||
from_fn(|_: DiagnosticContext| Ok::<_, Error>(ApiState::Error))
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_about("Display the API that is currently serving")
|
||||
.with_about("about.display-current-api")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"server",
|
||||
server::<C>()
|
||||
.with_about("Commands related to the server i.e. restart, update, and shutdown"),
|
||||
)
|
||||
.subcommand("server", server::<C>().with_about("about.commands-server"))
|
||||
.subcommand(
|
||||
"package",
|
||||
package::<C>().with_about("Commands related to packages"),
|
||||
package::<C>().with_about("about.commands-packages"),
|
||||
)
|
||||
.subcommand(
|
||||
"net",
|
||||
net::net_api::<C>().with_about("Network commands related to tor and dhcp"),
|
||||
net::net_api::<C>().with_about("about.network-commands"),
|
||||
)
|
||||
.subcommand(
|
||||
"auth",
|
||||
auth::auth::<C, RpcContext>()
|
||||
.with_about("Commands related to Authentication i.e. login, logout"),
|
||||
)
|
||||
.subcommand(
|
||||
"db",
|
||||
db::db::<C>().with_about("Commands to interact with the db i.e. dump, put, apply"),
|
||||
)
|
||||
.subcommand(
|
||||
"ssh",
|
||||
ssh::ssh::<C>()
|
||||
.with_about("Commands for interacting with ssh keys i.e. add, delete, list"),
|
||||
auth::auth::<C, RpcContext>().with_about("about.commands-authentication"),
|
||||
)
|
||||
.subcommand("db", db::db::<C>().with_about("about.commands-db"))
|
||||
.subcommand("ssh", ssh::ssh::<C>().with_about("about.commands-ssh-keys"))
|
||||
.subcommand(
|
||||
"wifi",
|
||||
net::wifi::wifi::<C>()
|
||||
.with_about("Commands related to wifi networks i.e. add, connect, delete"),
|
||||
)
|
||||
.subcommand(
|
||||
"disk",
|
||||
disk::disk::<C>().with_about("Commands for listing disk info and repairing"),
|
||||
net::wifi::wifi::<C>().with_about("about.commands-wifi"),
|
||||
)
|
||||
.subcommand("disk", disk::disk::<C>().with_about("about.commands-disk"))
|
||||
.subcommand(
|
||||
"notification",
|
||||
notifications::notification::<C>().with_about("Create, delete, or list notifications"),
|
||||
notifications::notification::<C>().with_about("about.commands-notifications"),
|
||||
)
|
||||
.subcommand(
|
||||
"backup",
|
||||
backup::backup::<C>()
|
||||
.with_about("Commands related to backup creation and backup targets"),
|
||||
backup::backup::<C>().with_about("about.commands-backup"),
|
||||
)
|
||||
.subcommand(
|
||||
"registry",
|
||||
@@ -219,7 +202,7 @@ pub fn main_api<C: Context>() -> ParentHandler<C> {
|
||||
)
|
||||
.subcommand(
|
||||
"registry",
|
||||
registry::registry_api::<CliContext>().with_about("Commands related to the registry"),
|
||||
registry::registry_api::<CliContext>().with_about("about.commands-registry"),
|
||||
)
|
||||
.subcommand(
|
||||
"tunnel",
|
||||
@@ -228,31 +211,26 @@ pub fn main_api<C: Context>() -> ParentHandler<C> {
|
||||
)
|
||||
.subcommand(
|
||||
"tunnel",
|
||||
tunnel::api::tunnel_api::<CliContext>().with_about("Commands related to StartTunnel"),
|
||||
)
|
||||
.subcommand(
|
||||
"s9pk",
|
||||
s9pk::rpc::s9pk().with_about("Commands for interacting with s9pk files"),
|
||||
tunnel::api::tunnel_api::<CliContext>().with_about("about.commands-tunnel"),
|
||||
)
|
||||
.subcommand("s9pk", s9pk::rpc::s9pk().with_about("about.commands-s9pk"))
|
||||
.subcommand(
|
||||
"util",
|
||||
util::rpc::util::<C>().with_about("Command for calculating the blake3 hash of a file"),
|
||||
util::rpc::util::<C>().with_about("about.command-blake3-hash"),
|
||||
)
|
||||
.subcommand(
|
||||
"init-key",
|
||||
from_fn_async(developer::init)
|
||||
.no_display()
|
||||
.with_about("Create developer key if it doesn't exist"),
|
||||
.with_about("about.create-developer-key"),
|
||||
)
|
||||
.subcommand(
|
||||
"pubkey",
|
||||
from_fn_blocking(developer::pubkey)
|
||||
.with_about("Get public key for developer private key"),
|
||||
from_fn_blocking(developer::pubkey).with_about("about.get-developer-pubkey"),
|
||||
)
|
||||
.subcommand(
|
||||
"diagnostic",
|
||||
diagnostic::diagnostic::<C>()
|
||||
.with_about("Commands to display logs, restart the server, etc"),
|
||||
diagnostic::diagnostic::<C>().with_about("about.commands-diagnostic"),
|
||||
)
|
||||
.subcommand("init", init::init_api::<C>())
|
||||
.subcommand("setup", setup::setup::<C>());
|
||||
@@ -265,7 +243,7 @@ pub fn main_api<C: Context>() -> ParentHandler<C> {
|
||||
"flash-os",
|
||||
from_fn_async(os_install::cli_install_os)
|
||||
.no_display()
|
||||
.with_about("Flash StartOS to a disk from a squashfs"),
|
||||
.with_about("about.flash-startos"),
|
||||
);
|
||||
}
|
||||
api
|
||||
@@ -280,29 +258,32 @@ pub fn server<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
system::display_time(handle.params, result)
|
||||
})
|
||||
.with_about("Display current time and server uptime")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.display-time-uptime")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"experimental",
|
||||
system::experimental::<C>()
|
||||
.with_about("Commands related to configuring experimental options such as zram and cpu governor"),
|
||||
system::experimental::<C>().with_about("about.commands-experimental"),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
system::logs::<RpcContext>().with_about("Display OS logs"),
|
||||
system::logs::<RpcContext>().with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display OS logs"),
|
||||
from_fn_async(logs::cli_logs::<RpcContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("about.display-os-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
system::kernel_logs::<RpcContext>().with_about("Display Kernel logs"),
|
||||
system::kernel_logs::<RpcContext>().with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"kernel-logs",
|
||||
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display Kernel logs"),
|
||||
from_fn_async(logs::cli_logs::<RpcContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("about.display-kernel-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"metrics",
|
||||
@@ -310,35 +291,31 @@ pub fn server<C: Context>() -> ParentHandler<C> {
|
||||
.root_handler(
|
||||
from_fn_async(system::metrics)
|
||||
.with_display_serializable()
|
||||
.with_about("Display information about the server i.e. temperature, RAM, CPU, and disk usage")
|
||||
.with_call_remote::<CliContext>()
|
||||
)
|
||||
.subcommand(
|
||||
"follow",
|
||||
from_fn_async(system::metrics_follow)
|
||||
.no_cli()
|
||||
.with_about("about.display-server-metrics")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand("follow", from_fn_async(system::metrics_follow).no_cli()),
|
||||
)
|
||||
.subcommand(
|
||||
"shutdown",
|
||||
from_fn_async(shutdown::shutdown)
|
||||
.no_display()
|
||||
.with_about("Shutdown the server")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.shutdown-server")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"restart",
|
||||
from_fn_async(shutdown::restart)
|
||||
.no_display()
|
||||
.with_about("Restart the server")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.restart-server")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"rebuild",
|
||||
from_fn_async(shutdown::rebuild)
|
||||
.no_display()
|
||||
.with_about("Teardown and rebuild service containers")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.teardown-rebuild-containers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"update",
|
||||
@@ -348,7 +325,9 @@ pub fn server<C: Context>() -> ParentHandler<C> {
|
||||
)
|
||||
.subcommand(
|
||||
"update",
|
||||
from_fn_async(update::cli_update_system).no_display().with_about("Check a given registry for StartOS updates and update if available"),
|
||||
from_fn_async(update::cli_update_system)
|
||||
.no_display()
|
||||
.with_about("about.check-update-startos"),
|
||||
)
|
||||
.subcommand(
|
||||
"update-firmware",
|
||||
@@ -363,37 +342,41 @@ pub fn server<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|_handle, result| {
|
||||
Ok(firmware::display_firmware_update_result(result))
|
||||
})
|
||||
.with_about("Update the mainboard's firmware to the latest firmware available in this version of StartOS if available. Note: This command does not reach out to the Internet")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.update-firmware")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"set-smtp",
|
||||
from_fn_async(system::set_system_smtp)
|
||||
.no_display()
|
||||
.with_about("Set system smtp server and credentials")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.set-smtp")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"test-smtp",
|
||||
"test-smtp",
|
||||
from_fn_async(system::test_smtp)
|
||||
.no_display()
|
||||
.with_about("Send test email using provided smtp server and credentials")
|
||||
.with_call_remote::<CliContext>()
|
||||
.with_about("about.test-smtp")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"clear-smtp",
|
||||
from_fn_async(system::clear_system_smtp)
|
||||
.no_display()
|
||||
.with_about("Remove system smtp server and credentials")
|
||||
.with_call_remote::<CliContext>()
|
||||
).subcommand("host", net::host::server_host_api::<C>().with_about("Commands for modifying the host for the system ui"))
|
||||
.with_about("about.clear-smtp")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"host",
|
||||
net::host::server_host_api::<C>().with_about("about.commands-host-system-ui"),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"action",
|
||||
action::action_api::<C>().with_about("Commands to get action input or run an action"),
|
||||
action::action_api::<C>().with_about("about.commands-action"),
|
||||
)
|
||||
.subcommand(
|
||||
"install",
|
||||
@@ -411,13 +394,13 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
"install",
|
||||
from_fn_async_local(install::cli_install)
|
||||
.no_display()
|
||||
.with_about("Install a package from a marketplace or via sideloading"),
|
||||
.with_about("about.install-package"),
|
||||
)
|
||||
.subcommand(
|
||||
"cancel-install",
|
||||
from_fn(install::cancel_install)
|
||||
.no_display()
|
||||
.with_about("Cancel an install of a package")
|
||||
.with_about("about.cancel-install-package")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -425,21 +408,21 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(install::uninstall)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a package")
|
||||
.with_about("about.remove-package")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"list",
|
||||
from_fn_async(install::list)
|
||||
.with_display_serializable()
|
||||
.with_about("List installed packages")
|
||||
.with_about("about.list-installed-packages")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"installed-version",
|
||||
from_fn_async(install::installed_version)
|
||||
.with_display_serializable()
|
||||
.with_about("Display installed version for a PackageId")
|
||||
.with_about("about.display-installed-version")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -447,7 +430,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(control::start)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Start a service")
|
||||
.with_about("about.start-service")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -455,7 +438,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(control::stop)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Stop a service")
|
||||
.with_about("about.stop-service")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -463,7 +446,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(control::restart)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Restart a service")
|
||||
.with_about("about.restart-service")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -471,7 +454,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(service::rebuild)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Rebuild service container")
|
||||
.with_about("about.rebuild-service-container")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -511,35 +494,34 @@ pub fn package<C: Context>() -> ParentHandler<C> {
|
||||
table.print_tty(false)?;
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List information related to the lxc containers i.e. CPU, Memory, Disk")
|
||||
.with_about("about.list-lxc-container-info")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand("logs", logs::package_logs())
|
||||
.subcommand(
|
||||
"logs",
|
||||
logs::package_logs().with_about("Display package logs"),
|
||||
logs::package_logs().with_about("about.display-package-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"logs",
|
||||
from_fn_async(logs::cli_logs::<RpcContext, logs::PackageIdParams>)
|
||||
.no_display()
|
||||
.with_about("Display package logs"),
|
||||
.with_about("about.display-package-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"backup",
|
||||
backup::package_backup::<C>()
|
||||
.with_about("Commands for restoring package(s) from backup"),
|
||||
backup::package_backup::<C>().with_about("about.commands-restore-backup"),
|
||||
)
|
||||
.subcommand(
|
||||
"attach",
|
||||
from_fn_async(service::attach)
|
||||
.with_metadata("get_session", Value::Bool(true))
|
||||
.with_about("Execute commands within a service container")
|
||||
.with_about("about.execute-commands-container")
|
||||
.no_cli(),
|
||||
)
|
||||
.subcommand("attach", from_fn_async(service::cli_attach).no_display())
|
||||
.subcommand(
|
||||
"host",
|
||||
net::host::host_api::<C>().with_about("Manage network hosts for a package"),
|
||||
net::host::host_api::<C>().with_about("about.manage-network-hosts-package"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -554,7 +554,7 @@ pub async fn journalctl(
|
||||
let mut child = follow_cmd.stdout(Stdio::piped()).spawn()?;
|
||||
let out =
|
||||
BufReader::new(child.stdout.take().ok_or_else(|| {
|
||||
Error::new(eyre!("No stdout available"), crate::ErrorKind::Journald)
|
||||
Error::new(eyre!("{}", t!("logs.no-stdout-available")), crate::ErrorKind::Journald)
|
||||
})?);
|
||||
|
||||
let journalctl_entries = LinesStream::new(out.lines());
|
||||
@@ -700,7 +700,7 @@ pub async fn follow_logs<Context: AsRef<RpcContinuations>>(
|
||||
RpcContinuation::ws(
|
||||
move |socket| async move {
|
||||
if let Err(e) = ws_handler(first_entry, stream, socket).await {
|
||||
tracing::error!("Error in log stream: {}", e);
|
||||
tracing::error!("{}", t!("logs.error-in-log-stream", error = e.to_string()));
|
||||
}
|
||||
},
|
||||
Duration::from_secs(30),
|
||||
|
||||
@@ -141,7 +141,7 @@ impl LxcManager {
|
||||
> 0
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("rootfs is not empty, refusing to delete"),
|
||||
eyre!("{}", t!("lxc.mod.rootfs-not-empty")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -249,6 +249,7 @@ impl LxcContainer {
|
||||
.arg("-R")
|
||||
.arg("+C")
|
||||
.arg(&log_mount_point)
|
||||
.env("LANG", "C.UTF-8")
|
||||
.invoke(ErrorKind::Filesystem)
|
||||
.await
|
||||
{
|
||||
@@ -381,7 +382,7 @@ impl LxcContainer {
|
||||
}
|
||||
if start.elapsed() > CONTAINER_DHCP_TIMEOUT {
|
||||
return Err(Error::new(
|
||||
eyre!("Timed out waiting for container to acquire DHCP lease"),
|
||||
eyre!("{}", t!("lxc.mod.dhcp-timeout")),
|
||||
ErrorKind::Timeout,
|
||||
));
|
||||
}
|
||||
@@ -407,9 +408,12 @@ impl LxcContainer {
|
||||
if !output.status.success() {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Command failed with exit code: {:?} \n Message: {:?}",
|
||||
output.status.code(),
|
||||
String::from_utf8(output.stderr)
|
||||
"{}",
|
||||
t!(
|
||||
"lxc.mod.command-failed",
|
||||
code = format!("{:?}", output.status.code()),
|
||||
message = format!("{:?}", String::from_utf8(output.stderr))
|
||||
)
|
||||
),
|
||||
ErrorKind::Docker,
|
||||
));
|
||||
@@ -437,7 +441,7 @@ impl LxcContainer {
|
||||
> 0
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("rootfs is not empty, refusing to delete"),
|
||||
eyre!("{}", t!("lxc.mod.rootfs-not-empty")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -473,13 +477,19 @@ impl LxcContainer {
|
||||
.await
|
||||
);
|
||||
return Err(Error::new(
|
||||
eyre!("timed out waiting for socket"),
|
||||
eyre!("{}", t!("lxc.mod.socket-timeout")),
|
||||
ErrorKind::Timeout,
|
||||
));
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
tracing::info!("Connected to socket in {:?}", started.elapsed());
|
||||
tracing::info!(
|
||||
"{}",
|
||||
t!(
|
||||
"lxc.mod.connected-to-socket",
|
||||
elapsed = format!("{:?}", started.elapsed())
|
||||
)
|
||||
);
|
||||
Ok(UnixRpcClient::new(sock_path))
|
||||
}
|
||||
|
||||
@@ -569,8 +579,11 @@ impl Drop for LxcContainer {
|
||||
fn drop(&mut self) {
|
||||
if !self.exited {
|
||||
tracing::warn!(
|
||||
"Container {} was ungracefully dropped. Cleaning up dangling containers...",
|
||||
&**self.guid
|
||||
"{}",
|
||||
t!(
|
||||
"lxc.mod.container-ungracefully-dropped",
|
||||
container = &**self.guid
|
||||
)
|
||||
);
|
||||
let rootfs = self.rootfs.take();
|
||||
let guid = std::mem::take(&mut self.guid);
|
||||
@@ -589,16 +602,25 @@ impl Drop for LxcContainer {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error reading logs from crashed container: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("lxc.mod.error-reading-crashed-logs", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}")
|
||||
}
|
||||
rootfs.unmount(true).await.log_err();
|
||||
drop(guid);
|
||||
if let Err(e) = manager.gc().await {
|
||||
tracing::error!("Error cleaning up dangling LXC containers: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"lxc.mod.error-cleaning-up-containers",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{e:?}")
|
||||
} else {
|
||||
tracing::info!("Successfully cleaned up dangling LXC containers");
|
||||
tracing::info!("{}", t!("lxc.mod.cleaned-up-containers"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ impl LocalAuthContext for RpcContext {
|
||||
}
|
||||
|
||||
fn unauthorized() -> Error {
|
||||
Error::new(eyre!("UNAUTHORIZED"), crate::ErrorKind::Authorization)
|
||||
Error::new(eyre!("{}", t!("middleware.auth.unauthorized")), crate::ErrorKind::Authorization)
|
||||
}
|
||||
|
||||
async fn check_from_header<C: LocalAuthContext>(header: Option<&HeaderValue>) -> Result<(), Error> {
|
||||
|
||||
@@ -146,7 +146,7 @@ impl HashSessionToken {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("UNAUTHORIZED"),
|
||||
eyre!("{}", t!("middleware.auth.unauthorized")),
|
||||
crate::ErrorKind::Authorization,
|
||||
))
|
||||
}
|
||||
@@ -221,7 +221,7 @@ impl ValidSessionToken {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("UNAUTHORIZED"),
|
||||
eyre!("{}", t!("middleware.auth.unauthorized")),
|
||||
crate::ErrorKind::Authorization,
|
||||
))
|
||||
}
|
||||
@@ -244,7 +244,7 @@ impl ValidSessionToken {
|
||||
C::access_sessions(db)
|
||||
.as_idx_mut(session_hash)
|
||||
.ok_or_else(|| {
|
||||
Error::new(eyre!("UNAUTHORIZED"), crate::ErrorKind::Authorization)
|
||||
Error::new(eyre!("{}", t!("middleware.auth.unauthorized")), crate::ErrorKind::Authorization)
|
||||
})?
|
||||
.mutate(|s| {
|
||||
s.last_active = Utc::now();
|
||||
@@ -305,7 +305,7 @@ impl<C: SessionAuthContext> Middleware<C> for SessionAuth {
|
||||
self.rate_limiter.mutate(|(count, time)| {
|
||||
if time.elapsed() < Duration::from_secs(20) && *count >= 3 {
|
||||
Err(Error::new(
|
||||
eyre!("Please limit login attempts to 3 per 20 seconds."),
|
||||
eyre!("{}", t!("middleware.auth.rate-limited-login")),
|
||||
crate::ErrorKind::RateLimited,
|
||||
))
|
||||
} else {
|
||||
|
||||
@@ -90,7 +90,7 @@ impl SignatureAuthContext for RpcContext {
|
||||
}
|
||||
|
||||
Err(Error::new(
|
||||
eyre!("Key is not authorized"),
|
||||
eyre!("{}", t!("middleware.auth.key-not-authorized")),
|
||||
ErrorKind::IncorrectPassword,
|
||||
))
|
||||
}
|
||||
@@ -141,7 +141,7 @@ impl SignatureAuth {
|
||||
let mut cache = self.nonce_cache.lock().await;
|
||||
if cache.values().any(|n| *n == nonce) {
|
||||
return Err(Error::new(
|
||||
eyre!("replay attack detected"),
|
||||
eyre!("{}", t!("middleware.auth.replay-attack-detected")),
|
||||
ErrorKind::Authorization,
|
||||
));
|
||||
}
|
||||
@@ -226,7 +226,7 @@ impl<C: SignatureAuthContext> Middleware<C> for SignatureAuth {
|
||||
|
||||
context.sig_context().await.into_iter().fold(
|
||||
Err(Error::new(
|
||||
eyre!("no valid signature context available to verify"),
|
||||
eyre!("{}", t!("middleware.auth.no-valid-sig-context")),
|
||||
ErrorKind::Authorization,
|
||||
)),
|
||||
|acc, x| {
|
||||
@@ -249,7 +249,7 @@ impl<C: SignatureAuthContext> Middleware<C> for SignatureAuth {
|
||||
.unwrap_or_else(|e| e.duration().as_secs() as i64 * -1);
|
||||
if (now - commitment.timestamp).abs() > 30 {
|
||||
return Err(Error::new(
|
||||
eyre!("timestamp not within 30s of now"),
|
||||
eyre!("{}", t!("middleware.auth.timestamp-not-within-30s")),
|
||||
ErrorKind::InvalidSignature,
|
||||
));
|
||||
}
|
||||
@@ -347,6 +347,6 @@ pub async fn call_remote<Ctx: SigningContext + AsRef<Client>>(
|
||||
.with_kind(ErrorKind::Deserialization)?
|
||||
.result
|
||||
}
|
||||
_ => Err(Error::new(eyre!("unknown content type"), ErrorKind::Network).into()),
|
||||
_ => Err(Error::new(eyre!("{}", t!("middleware.auth.unknown-content-type")), ErrorKind::Network).into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use axum::response::Response;
|
||||
use http::HeaderValue;
|
||||
use http::header::InvalidHeaderValue;
|
||||
use rpc_toolkit::{Middleware, RpcRequest, RpcResponse};
|
||||
use rust_i18n::t;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::context::RpcContext;
|
||||
@@ -46,7 +47,7 @@ impl Middleware<RpcContext> for SyncDb {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("error writing X-Patch-Sequence header: {e}");
|
||||
tracing::error!("{}", t!("middleware.db.error-writing-patch-sequence-header", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ pub fn acme_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(init)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Setup ACME certificate acquisition")
|
||||
.with_about("about.setup-acme-certificate-acquisition")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -403,7 +403,7 @@ pub fn acme_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove ACME certificate acquisition configuration")
|
||||
.with_about("about.remove-acme-certificate-acquisition-configuration")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ pub fn dns_api<C: Context>() -> ParentHandler<C> {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Test the DNS configuration for a domain"),
|
||||
.with_about("about.test-dns-configuration-for-domain"),
|
||||
)
|
||||
.subcommand(
|
||||
"set-static",
|
||||
from_fn_async(set_static_dns)
|
||||
.no_display()
|
||||
.with_about("Set static DNS servers")
|
||||
.with_about("about.set-static-dns-servers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -88,7 +88,7 @@ pub fn dns_api<C: Context>() -> ParentHandler<C> {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Dump address resolution table")
|
||||
.with_about("about.dump-address-resolution-table")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -292,7 +292,7 @@ impl Resolver {
|
||||
.await
|
||||
.map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("timed out waiting to update dns catalog"),
|
||||
eyre!("{}", t!("net.dns.timeout-updating-catalog")),
|
||||
ErrorKind::Timeout,
|
||||
)
|
||||
})?;
|
||||
@@ -348,7 +348,13 @@ impl Resolver {
|
||||
}) {
|
||||
return Some(res);
|
||||
} else {
|
||||
tracing::warn!("Could not determine source interface of {src}");
|
||||
tracing::warn!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.dns.could-not-determine-source-interface",
|
||||
src = src.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if STARTOS.zone_of(name) || EMBASSY.zone_of(name) {
|
||||
@@ -473,7 +479,10 @@ impl RequestHandler for Resolver {
|
||||
Ok(Some(a)) => return a,
|
||||
Ok(None) => (),
|
||||
Err(e) => {
|
||||
tracing::error!("Error resolving internal DNS: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.dns.error-resolving-internal", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
let mut header = Header::response_from_request(request.header());
|
||||
header.set_recursion_available(true);
|
||||
@@ -557,7 +566,7 @@ impl DnsController {
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("DNS Server Thread has exited"),
|
||||
eyre!("{}", t!("net.dns.server-thread-exited")),
|
||||
crate::ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
@@ -577,7 +586,7 @@ impl DnsController {
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("DNS Server Thread has exited"),
|
||||
eyre!("{}", t!("net.dns.server-thread-exited")),
|
||||
crate::ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
@@ -598,7 +607,7 @@ impl DnsController {
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("DNS Server Thread has exited"),
|
||||
eyre!("{}", t!("net.dns.server-thread-exited")),
|
||||
crate::ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
@@ -624,7 +633,7 @@ impl DnsController {
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("DNS Server Thread has exited"),
|
||||
eyre!("{}", t!("net.dns.server-thread-exited")),
|
||||
crate::ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ impl AvailablePorts {
|
||||
pub fn alloc(&mut self) -> Result<u16, Error> {
|
||||
self.0.request_id().ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("No more dynamic ports available!"),
|
||||
eyre!("{}", t!("net.forward.no-dynamic-ports-available")),
|
||||
ErrorKind::Network,
|
||||
)
|
||||
})
|
||||
@@ -240,7 +240,7 @@ impl PortForwardController {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("error initializing PortForwardController: {e:#}");
|
||||
tracing::error!("{}", t!("net.forward.error-initializing-controller", error = format!("{e:#}")));
|
||||
tracing::debug!("{e:?}");
|
||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
}
|
||||
@@ -400,7 +400,7 @@ impl InterfaceForwardEntry {
|
||||
) -> Result<Arc<()>, Error> {
|
||||
if external != self.external {
|
||||
return Err(Error::new(
|
||||
eyre!("Mismatched external port in InterfaceForwardEntry"),
|
||||
eyre!("{}", t!("net.forward.mismatched-external-port")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -477,7 +477,7 @@ impl InterfaceForwardState {
|
||||
|
||||
fn err_has_exited<T>(_: T) -> Error {
|
||||
Error::new(
|
||||
eyre!("PortForwardController thread has exited"),
|
||||
eyre!("{}", t!("net.forward.controller-thread-exited")),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ pub fn gateway_api<C: Context>() -> ParentHandler<C> {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Show gateways StartOS can listen on")
|
||||
.with_about("about.show-gateways-startos-can-listen-on")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -103,7 +103,7 @@ pub fn gateway_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(set_public)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Indicate whether this gateway has inbound access from the WAN")
|
||||
.with_about("about.indicate-gateway-inbound-access-from-wan")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -111,10 +111,7 @@ pub fn gateway_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(unset_public)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about(concat!(
|
||||
"Allow this gateway to infer whether it has",
|
||||
" inbound access from the WAN based on its IPv4 address"
|
||||
))
|
||||
.with_about("about.allow-gateway-infer-inbound-access-from-wan")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -122,7 +119,7 @@ pub fn gateway_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(forget_iface)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Forget a disconnected gateway")
|
||||
.with_about("about.forget-disconnected-gateway")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -130,7 +127,7 @@ pub fn gateway_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(set_name)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Rename a gateway")
|
||||
.with_about("about.rename-gateway")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -464,7 +461,8 @@ async fn watcher(
|
||||
ensure_code!(
|
||||
!devices.is_empty(),
|
||||
ErrorKind::Network,
|
||||
"NetworkManager returned no devices. Trying again..."
|
||||
"{}",
|
||||
t!("net.gateway.no-devices-returned")
|
||||
);
|
||||
let mut ifaces = BTreeSet::new();
|
||||
let mut jobs = Vec::new();
|
||||
@@ -731,7 +729,8 @@ async fn watch_ip(
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
"Failed to determine WAN IP for {iface}: {e}"
|
||||
"{}",
|
||||
t!("net.gateway.failed-to-determine-wan-ip", iface = iface.to_string(), error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
None
|
||||
@@ -1021,7 +1020,13 @@ impl NetworkInterfaceController {
|
||||
info
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Error loading network interface info: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.gateway.error-loading-interface-info",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
OrdMap::new()
|
||||
}
|
||||
@@ -1050,7 +1055,10 @@ impl NetworkInterfaceController {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error syncing ip info to db: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.gateway.error-syncing-ip-info", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
|
||||
@@ -1060,7 +1068,10 @@ impl NetworkInterfaceController {
|
||||
}
|
||||
.await;
|
||||
if let Err(e) = res {
|
||||
tracing::error!("Error syncing ip info to db: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.gateway.error-syncing-ip-info", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
})
|
||||
@@ -1121,7 +1132,7 @@ impl NetworkInterfaceController {
|
||||
.map_or(false, |i| i.ip_info.is_some())
|
||||
{
|
||||
err = Some(Error::new(
|
||||
eyre!("Cannot forget currently connected interface"),
|
||||
eyre!("{}", t!("net.gateway.cannot-forget-connected-interface")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
return false;
|
||||
@@ -1167,7 +1178,7 @@ impl NetworkInterfaceController {
|
||||
|
||||
if &*ac == "/" {
|
||||
return Err(Error::new(
|
||||
eyre!("Cannot delete device without active connection"),
|
||||
eyre!("{}", t!("net.gateway.cannot-delete-without-connection")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Add a public domain to this host")
|
||||
.with_about("about.add-public-domain-to-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -129,7 +129,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Remove a public domain from this host")
|
||||
.with_about("about.remove-public-domain-from-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.with_inherited(|_, a| a),
|
||||
@@ -143,7 +143,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Add a private domain to this host")
|
||||
.with_about("about.add-private-domain-to-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -152,7 +152,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Remove a private domain from this host")
|
||||
.with_about("about.remove-private-domain-from-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.with_inherited(|_, a| a),
|
||||
@@ -168,7 +168,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Add an address to this host")
|
||||
.with_about("about.add-address-to-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -177,7 +177,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|_, a| a)
|
||||
.no_display()
|
||||
.with_about("Remove an address from this host")
|
||||
.with_about("about.remove-address-from-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.with_inherited(Kind::inheritance),
|
||||
@@ -230,7 +230,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List addresses for this host")
|
||||
.with_about("about.list-addresses-for-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ pub fn binding<C: Context, Kind: HostApiKind>()
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List bindinges for this host")
|
||||
.with_about("about.list-bindings-for-host")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -218,7 +218,7 @@ pub fn binding<C: Context, Kind: HostApiKind>()
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(Kind::inheritance)
|
||||
.no_display()
|
||||
.with_about("Set whether this gateway should be enabled for this binding")
|
||||
.with_about("about.set-gateway-enabled-for-binding")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ pub fn host_api<C: Context>() -> ParentHandler<C, RequiresPackageId> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List host IDs available for this service"),
|
||||
.with_about("about.list-host-ids-for-service"),
|
||||
)
|
||||
.subcommand(
|
||||
"address",
|
||||
|
||||
@@ -23,32 +23,29 @@ pub mod wifi;
|
||||
|
||||
pub fn net_api<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"tor",
|
||||
tor::tor_api::<C>().with_about("Tor commands such as list-services, logs, and reset"),
|
||||
)
|
||||
.subcommand("tor", tor::tor_api::<C>().with_about("about.tor-commands"))
|
||||
.subcommand(
|
||||
"acme",
|
||||
acme::acme_api::<C>().with_about("Setup automatic clearnet certificate acquisition"),
|
||||
acme::acme_api::<C>().with_about("about.setup-acme-certificate"),
|
||||
)
|
||||
.subcommand(
|
||||
"dns",
|
||||
dns::dns_api::<C>().with_about("Manage and query DNS"),
|
||||
dns::dns_api::<C>().with_about("about.manage-query-dns"),
|
||||
)
|
||||
.subcommand(
|
||||
"forward",
|
||||
forward::forward_api::<C>().with_about("Manage port forwards"),
|
||||
forward::forward_api::<C>().with_about("about.manage-port-forwards"),
|
||||
)
|
||||
.subcommand(
|
||||
"gateway",
|
||||
gateway::gateway_api::<C>().with_about("View and edit gateway configurations"),
|
||||
gateway::gateway_api::<C>().with_about("about.view-edit-gateway-configs"),
|
||||
)
|
||||
.subcommand(
|
||||
"tunnel",
|
||||
tunnel::tunnel_api::<C>().with_about("Manage tunnels"),
|
||||
tunnel::tunnel_api::<C>().with_about("about.manage-tunnels"),
|
||||
)
|
||||
.subcommand(
|
||||
"vhost",
|
||||
vhost::vhost_api::<C>().with_about("Manage ssl virtual host proxy"),
|
||||
vhost::vhost_api::<C>().with_about("about.manage-ssl-vhost-proxy"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ impl FullchainCertData {
|
||||
]
|
||||
.into_iter()
|
||||
.min()
|
||||
.ok_or_else(|| Error::new(eyre!("unreachable"), ErrorKind::Unknown))
|
||||
.ok_or_else(|| Error::new(eyre!("{}", t!("net.ssl.unreachable")), ErrorKind::Unknown))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,10 @@ impl TorSecretKey {
|
||||
Ok(Self(
|
||||
tor_llcrypto::pk::ed25519::ExpandedKeypair::from_secret_key_bytes(bytes)
|
||||
.ok_or_else(|| {
|
||||
Error::new(eyre!("invalid ed25519 expanded secret key"), ErrorKind::Tor)
|
||||
Error::new(
|
||||
eyre!("{}", t!("net.tor.invalid-ed25519-key")),
|
||||
ErrorKind::Tor,
|
||||
)
|
||||
})?
|
||||
.into(),
|
||||
))
|
||||
@@ -226,19 +229,19 @@ pub fn tor_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(list_services)
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_services(handle.params, result))
|
||||
.with_about("Display Tor V3 Onion Addresses")
|
||||
.with_about("about.display-tor-v3-onion-addresses")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"reset",
|
||||
from_fn_async(reset)
|
||||
.no_display()
|
||||
.with_about("Reset Tor daemon")
|
||||
.with_about("about.reset-tor-daemon")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"key",
|
||||
key::<C>().with_about("Manage the onion service key store"),
|
||||
key::<C>().with_about("about.manage-onion-service-key-store"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -247,13 +250,13 @@ pub fn key<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"generate",
|
||||
from_fn_async(generate_key)
|
||||
.with_about("Generate an onion service key and add it to the key store")
|
||||
.with_about("about.generate-onion-service-key-add-to-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"add",
|
||||
from_fn_async(add_key)
|
||||
.with_about("Add an onion service key to the key store")
|
||||
.with_about("about.add-onion-service-key-to-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -265,7 +268,7 @@ pub fn key<C: Context>() -> ParentHandler<C> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List onion services with keys in the key store")
|
||||
.with_about("about.list-onion-services-with-keys-in-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -447,9 +450,13 @@ impl TorController {
|
||||
if prev_inst.elapsed() > BOOTSTRAP_PROGRESS_TIMEOUT {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Bootstrap has not made progress for {}",
|
||||
crate::util::serde::Duration::from(
|
||||
BOOTSTRAP_PROGRESS_TIMEOUT
|
||||
"{}",
|
||||
t!(
|
||||
"net.tor.bootstrap-no-progress",
|
||||
duration = crate::util::serde::Duration::from(
|
||||
BOOTSTRAP_PROGRESS_TIMEOUT
|
||||
)
|
||||
.to_string()
|
||||
)
|
||||
),
|
||||
ErrorKind::Tor,
|
||||
@@ -466,7 +473,10 @@ impl TorController {
|
||||
res = bootstrap_fut => res,
|
||||
res = failure_fut => res,
|
||||
} {
|
||||
tracing::error!("Tor Bootstrap Error: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.tor.bootstrap-error", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
} else {
|
||||
bootstrapper_client.send_modify(|_| ());
|
||||
@@ -516,7 +526,13 @@ impl TorController {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Tor Health Error: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.tor.health-error",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
});
|
||||
@@ -529,7 +545,10 @@ impl TorController {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("status event stream ended"),
|
||||
eyre!(
|
||||
"{}",
|
||||
t!("net.tor.status-stream-ended")
|
||||
),
|
||||
ErrorKind::Tor,
|
||||
))
|
||||
})
|
||||
@@ -560,13 +579,19 @@ impl TorController {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Tor Client Health Error: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.tor.client-health-error", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
tracing::error!(
|
||||
"Client failed health check {} times, recycling",
|
||||
HEALTH_CHECK_FAILURE_ALLOWANCE
|
||||
"{}",
|
||||
t!(
|
||||
"net.tor.health-check-failed-recycling",
|
||||
count = HEALTH_CHECK_FAILURE_ALLOWANCE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -574,7 +599,10 @@ impl TorController {
|
||||
})
|
||||
.await
|
||||
{
|
||||
tracing::error!("Tor Bootstrapper Error: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.tor.bootstrapper-error", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
if let Err::<(), Error>(e) = async {
|
||||
@@ -592,7 +620,10 @@ impl TorController {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Tor Client Creation Error: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.tor.client-creation-error", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
@@ -684,7 +715,10 @@ impl TorController {
|
||||
.await
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
if let Err(e) = socket2::SockRef::from(&tcp_stream).set_keepalive(true) {
|
||||
tracing::error!("Failed to set tcp keepalive: {e}");
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!("net.tor.failed-to-set-tcp-keepalive", error = e.to_string())
|
||||
);
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
Ok(Box::new(tcp_stream))
|
||||
@@ -812,7 +846,7 @@ impl OnionService {
|
||||
.await
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
if let Err(e) = socket2::SockRef::from(&outgoing).set_keepalive(true) {
|
||||
tracing::error!("Failed to set tcp keepalive: {e}");
|
||||
tracing::error!("{}", t!("net.tor.failed-to-set-tcp-keepalive", error = e.to_string()));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
let mut incoming = req
|
||||
@@ -852,7 +886,7 @@ impl OnionService {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Tor Client Error: {e}");
|
||||
tracing::error!("{}", t!("net.tor.client-error", error = e.to_string()));
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,26 +249,26 @@ pub fn tor_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(list_services)
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_services(handle.params, result))
|
||||
.with_about("Display Tor V3 Onion Addresses")
|
||||
.with_about("about.display-tor-v3-onion-addresses")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand("logs", logs().with_about("Display Tor logs"))
|
||||
.subcommand("logs", logs().with_about("about.display-tor-logs"))
|
||||
.subcommand(
|
||||
"logs",
|
||||
from_fn_async(crate::logs::cli_logs::<RpcContext, Empty>)
|
||||
.no_display()
|
||||
.with_about("Display Tor logs"),
|
||||
.with_about("about.display-tor-logs"),
|
||||
)
|
||||
.subcommand(
|
||||
"reset",
|
||||
from_fn_async(reset)
|
||||
.no_display()
|
||||
.with_about("Reset Tor daemon")
|
||||
.with_about("about.reset-tor-daemon")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"key",
|
||||
key::<C>().with_about("Manage the onion service key store"),
|
||||
key::<C>().with_about("about.manage-onion-service-key-store"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -277,13 +277,13 @@ pub fn key<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"generate",
|
||||
from_fn_async(generate_key)
|
||||
.with_about("Generate an onion service key and add it to the key store")
|
||||
.with_about("about.generate-onion-service-key-add-to-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"add",
|
||||
from_fn_async(add_key)
|
||||
.with_about("Add an onion service key to the key store")
|
||||
.with_about("about.add-onion-service-key-to-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -295,7 +295,7 @@ pub fn key<C: Context>() -> ParentHandler<C> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List onion services with keys in the key store")
|
||||
.with_about("about.list-onion-services-with-keys-in-store")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"add",
|
||||
from_fn_async(add_tunnel)
|
||||
.with_about("Add a new tunnel")
|
||||
.with_about("about.add-new-tunnel")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove_tunnel)
|
||||
.no_display()
|
||||
.with_about("Remove a tunnel")
|
||||
.with_about("about.remove-tunnel")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ type WifiManager = Arc<RwLock<Option<WpaCli>>>;
|
||||
// Ok(wifi_manager)
|
||||
// } else {
|
||||
// Err(Error::new(
|
||||
// color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
// color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
// ErrorKind::Wifi,
|
||||
// ))
|
||||
// }
|
||||
@@ -42,28 +42,28 @@ pub fn wifi<C: Context>() -> ParentHandler<C> {
|
||||
"set-enabled",
|
||||
from_fn_async(set_enabled)
|
||||
.no_display()
|
||||
.with_about("Enable or disable wifi")
|
||||
.with_about("about.enable-disable-wifi")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"add",
|
||||
from_fn_async(add)
|
||||
.no_display()
|
||||
.with_about("Add wifi ssid and password")
|
||||
.with_about("about.add-wifi-ssid-password")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"connect",
|
||||
from_fn_async(connect)
|
||||
.no_display()
|
||||
.with_about("Connect to wifi network")
|
||||
.with_about("about.connect-wifi-network")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove)
|
||||
.no_display()
|
||||
.with_about("Remove a wifi network")
|
||||
.with_about("about.remove-wifi-network")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -71,16 +71,16 @@ pub fn wifi<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(get)
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_wifi_info(handle.params, result))
|
||||
.with_about("List wifi info")
|
||||
.with_about("about.list-wifi-info")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"country",
|
||||
country::<C>().with_about("Command to set country"),
|
||||
country::<C>().with_about("about.command-set-country"),
|
||||
)
|
||||
.subcommand(
|
||||
"available",
|
||||
available::<C>().with_about("Command to list available wifi networks"),
|
||||
available::<C>().with_about("about.command-list-available-wifi"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ pub fn available<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(get_available)
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_wifi_list(handle.params, result))
|
||||
.with_about("List available wifi networks")
|
||||
.with_about("about.list-available-wifi-networks")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -143,7 +143,7 @@ pub fn country<C: Context>() -> ParentHandler<C> {
|
||||
"set",
|
||||
from_fn_async(set_country)
|
||||
.no_display()
|
||||
.with_about("Set Country")
|
||||
.with_about("about.set-country")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -160,13 +160,13 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re
|
||||
let wifi_manager = ctx.wifi_manager.clone();
|
||||
if !ssid.is_ascii() {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("SSID may not have special characters"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
if !password.is_ascii() {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("WiFi Password may not have special characters"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.password-no-special-characters")),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -176,11 +176,11 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re
|
||||
ssid: &Ssid,
|
||||
password: &Psk,
|
||||
) -> Result<(), Error> {
|
||||
tracing::info!("Adding new WiFi network: '{}'", ssid.0);
|
||||
tracing::info!("{}", t!("net.wifi.adding-network", ssid = &ssid.0));
|
||||
let mut wpa_supplicant = wifi_manager.write_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
@@ -195,10 +195,17 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::error!("Failed to add new WiFi network '{}': {}", ssid, err);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.wifi.failed-to-add-network",
|
||||
ssid = &ssid,
|
||||
error = err.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", err);
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("Failed adding {}", ssid),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.failed-adding", ssid = &ssid)),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -230,7 +237,7 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result
|
||||
let wifi_manager = ctx.wifi_manager.clone();
|
||||
if !ssid.is_ascii() {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("SSID may not have special characters"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -242,19 +249,19 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result
|
||||
let mut wpa_supplicant = wifi_manager.write_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
let current = wpa_supplicant.get_current_network().await?;
|
||||
let connected = wpa_supplicant.select_network(db.clone(), ssid).await?;
|
||||
if connected {
|
||||
tracing::info!("Successfully connected to WiFi: '{}'", ssid.0);
|
||||
tracing::info!("{}", t!("net.wifi.connected-successfully", ssid = &ssid.0));
|
||||
} else {
|
||||
tracing::info!("Failed to connect to WiFi: '{}'", ssid.0);
|
||||
tracing::info!("{}", t!("net.wifi.connection-failed", ssid = &ssid.0));
|
||||
match current {
|
||||
None => {
|
||||
tracing::info!("No WiFi to revert to!");
|
||||
tracing::info!("{}", t!("net.wifi.no-wifi-to-revert"));
|
||||
}
|
||||
Some(current) => {
|
||||
wpa_supplicant.select_network(db, ¤t).await?;
|
||||
@@ -267,9 +274,16 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result
|
||||
if let Err(err) =
|
||||
connect_procedure(ctx.db.clone(), wifi_manager.clone(), &Ssid(ssid.clone())).await
|
||||
{
|
||||
tracing::error!("Failed to connect to WiFi network '{}': {}", &ssid, err);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.wifi.failed-to-connect",
|
||||
ssid = &ssid,
|
||||
error = err.to_string()
|
||||
)
|
||||
);
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("Can't connect to {}", ssid),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.cant-connect", ssid = &ssid)),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -297,7 +311,7 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
|
||||
let wifi_manager = ctx.wifi_manager.clone();
|
||||
if !ssid.is_ascii() {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("SSID may not have special characters"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -305,7 +319,7 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
|
||||
let mut wpa_supplicant = wifi_manager.write_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
@@ -316,9 +330,7 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
|
||||
is_current_being_removed && !interface_connected(&ctx.ethernet_interface).await?;
|
||||
if is_current_removed_and_no_hardwire {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!(
|
||||
"Forbidden: Deleting this network would make your server unreachable. Either connect to ethernet or connect to a different WiFi network to remedy this."
|
||||
),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.forbidden-delete-would-disconnect")),
|
||||
ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
@@ -463,7 +475,7 @@ pub async fn get(ctx: RpcContext, _: Empty) -> Result<WifiListInfo, Error> {
|
||||
let wpa_supplicant = wifi_manager.read_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_ref().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
@@ -517,7 +529,7 @@ pub async fn get_available(ctx: RpcContext, _: Empty) -> Result<Vec<WifiListOut>
|
||||
let wpa_supplicant = wifi_manager.read_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_ref().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
@@ -558,14 +570,14 @@ pub async fn set_country(
|
||||
let wifi_manager = ctx.wifi_manager.clone();
|
||||
if !interface_connected(&ctx.ethernet_interface).await? {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("Won't change country without hardwire connection"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.wont-change-country-without-ethernet")),
|
||||
crate::ErrorKind::Wifi,
|
||||
));
|
||||
}
|
||||
let mut wpa_supplicant = wifi_manager.write_owned().await;
|
||||
let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("No WiFi interface available"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
@@ -684,7 +696,14 @@ impl WpaCli {
|
||||
.await
|
||||
.map(|_| ())
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::warn!("Failed to set interface {} for {}", self.interface, ssid.0);
|
||||
tracing::warn!(
|
||||
"{}",
|
||||
t!(
|
||||
"net.wifi.failed-to-set-interface",
|
||||
interface = &self.interface,
|
||||
ssid = &ssid.0
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
});
|
||||
Command::new("nmcli")
|
||||
@@ -719,13 +738,13 @@ impl WpaCli {
|
||||
}
|
||||
let first_country = r.lines().find(|s| s.contains("country")).ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Could not find a country config lines"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.could-not-find-country-config")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?;
|
||||
let country = &RE.captures(first_country).ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Could not find a country config with regex"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.could-not-parse-country-config")),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?[1];
|
||||
@@ -734,7 +753,10 @@ impl WpaCli {
|
||||
} else {
|
||||
Ok(Some(CountryCode::for_alpha2(country).map_err(|_| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Invalid Country Code: {}", country),
|
||||
color_eyre::eyre::eyre!(
|
||||
"{}",
|
||||
t!("net.wifi.invalid-country-code", country = country)
|
||||
),
|
||||
ErrorKind::Wifi,
|
||||
)
|
||||
})?))
|
||||
@@ -877,7 +899,7 @@ impl WpaCli {
|
||||
let m_id = self.check_active_network(ssid).await?;
|
||||
match m_id {
|
||||
None => Err(Error::new(
|
||||
color_eyre::eyre::eyre!("SSID Not Found"),
|
||||
color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-not-found")),
|
||||
ErrorKind::Wifi,
|
||||
)),
|
||||
Some(x) => {
|
||||
@@ -1058,7 +1080,7 @@ pub async fn synchronize_network_manager<P: AsRef<Path>>(
|
||||
.invoke(ErrorKind::Wifi)
|
||||
.await?;
|
||||
if let Some(last_country_code) = wifi.last_region {
|
||||
tracing::info!("Setting the region");
|
||||
tracing::info!("{}", t!("net.wifi.setting-region"));
|
||||
let _ = Command::new("iw")
|
||||
.arg("reg")
|
||||
.arg("set")
|
||||
@@ -1066,7 +1088,7 @@ pub async fn synchronize_network_manager<P: AsRef<Path>>(
|
||||
.invoke(ErrorKind::Wifi)
|
||||
.await?;
|
||||
} else {
|
||||
tracing::info!("Setting the region fallback");
|
||||
tracing::info!("{}", t!("net.wifi.setting-region-fallback"));
|
||||
let _ = Command::new("iw")
|
||||
.arg("reg")
|
||||
.arg("set")
|
||||
|
||||
@@ -27,49 +27,49 @@ pub fn notification<C: Context>() -> ParentHandler<C> {
|
||||
"list",
|
||||
from_fn_async(list)
|
||||
.with_display_serializable()
|
||||
.with_about("List notifications")
|
||||
.with_about("about.list-notifications")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove)
|
||||
.no_display()
|
||||
.with_about("Remove notification for given ids")
|
||||
.with_about("about.remove-notification-for-ids")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove-before",
|
||||
from_fn_async(remove_before)
|
||||
.no_display()
|
||||
.with_about("Remove notifications preceding a given id")
|
||||
.with_about("about.remove-notifications-before-id")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"mark-seen",
|
||||
from_fn_async(mark_seen)
|
||||
.no_display()
|
||||
.with_about("Mark given notifications as seen")
|
||||
.with_about("about.mark-notifications-seen")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"mark-seen-before",
|
||||
from_fn_async(mark_seen_before)
|
||||
.no_display()
|
||||
.with_about("Mark notifications preceding a given id as seen")
|
||||
.with_about("about.mark-notifications-seen-before-id")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"mark-unseen",
|
||||
from_fn_async(mark_unseen)
|
||||
.no_display()
|
||||
.with_about("Mark given notifications as unseen")
|
||||
.with_about("about.mark-notifications-unseen")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"create",
|
||||
from_fn_async(create)
|
||||
.no_display()
|
||||
.with_about("Persist a newly created notification")
|
||||
.with_about("about.persist-new-notification")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -346,7 +346,7 @@ pub struct InvalidNotificationLevel(String);
|
||||
impl From<InvalidNotificationLevel> for crate::Error {
|
||||
fn from(val: InvalidNotificationLevel) -> Self {
|
||||
Error::new(
|
||||
eyre!("Invalid Notification Level: {}", val.0),
|
||||
eyre!("{}", t!("notifications.invalid-level", level = val.0)),
|
||||
ErrorKind::ParseDbField,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pub use color_eyre::eyre::eyre;
|
||||
pub use imbl_value::InternedString;
|
||||
pub use lazy_format::lazy_format;
|
||||
pub use rust_i18n::t;
|
||||
pub use tracing::instrument;
|
||||
|
||||
pub use crate::db::prelude::*;
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn admin_api<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"signer",
|
||||
signers_api::<C>().with_about("Commands to add or list signers"),
|
||||
signers_api::<C>().with_about("about.commands-add-list-signers"),
|
||||
)
|
||||
.subcommand(
|
||||
"add",
|
||||
@@ -33,14 +33,14 @@ pub fn admin_api<C: Context>() -> ParentHandler<C> {
|
||||
"add",
|
||||
from_fn_async(cli_add_admin)
|
||||
.no_display()
|
||||
.with_about("Add admin signer"),
|
||||
.with_about("about.add-admin-signer"),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove_admin)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove an admin signer")
|
||||
.with_about("about.remove-admin-signer")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -49,7 +49,7 @@ pub fn admin_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_signers(handle.params, result))
|
||||
.with_about("List admin signers")
|
||||
.with_about("about.list-admin-signers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ fn signers_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_signers(handle.params, result))
|
||||
.with_about("List signers")
|
||||
.with_about("about.list-signers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -73,7 +73,7 @@ fn signers_api<C: Context>() -> ParentHandler<C> {
|
||||
)
|
||||
.subcommand(
|
||||
"add",
|
||||
from_fn_async(cli_add_signer).with_about("Add signer"),
|
||||
from_fn_async(cli_add_signer).with_about("about.add-signer"),
|
||||
)
|
||||
.subcommand(
|
||||
"edit",
|
||||
@@ -93,7 +93,7 @@ impl Model<BTreeMap<Guid, SignerInfo>> {
|
||||
.next()
|
||||
.transpose()?
|
||||
.map(|(a, _)| a)
|
||||
.ok_or_else(|| Error::new(eyre!("unknown signer"), ErrorKind::Authorization))
|
||||
.ok_or_else(|| Error::new(eyre!("{}", t!("registry.admin.unknown-signer")), ErrorKind::Authorization))
|
||||
}
|
||||
|
||||
pub fn get_signer_info(&self, key: &AnyVerifyingKey) -> Result<(Guid, SignerInfo), Error> {
|
||||
@@ -103,7 +103,7 @@ impl Model<BTreeMap<Guid, SignerInfo>> {
|
||||
.filter_ok(|(_, s)| s.keys.contains(key))
|
||||
.next()
|
||||
.transpose()?
|
||||
.ok_or_else(|| Error::new(eyre!("unknown signer"), ErrorKind::Authorization))
|
||||
.ok_or_else(|| Error::new(eyre!("{}", t!("registry.admin.unknown-signer")), ErrorKind::Authorization))
|
||||
}
|
||||
|
||||
pub fn add_signer(&mut self, signer: &SignerInfo) -> Result<Guid, Error> {
|
||||
@@ -117,9 +117,8 @@ impl Model<BTreeMap<Guid, SignerInfo>> {
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"A signer {} ({}) already exists with a matching key",
|
||||
guid,
|
||||
s.name
|
||||
"{}",
|
||||
t!("registry.admin.signer-already-exists", guid = guid, name = s.name)
|
||||
),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
|
||||
@@ -49,7 +49,7 @@ impl<Commitment> RegistryAsset<Commitment> {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Failed to load any http url"),
|
||||
eyre!("{}", t!("registry.asset.failed-to-load-http-url")),
|
||||
ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
@@ -64,7 +64,7 @@ impl<Commitment> RegistryAsset<Commitment> {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Failed to load any http url"),
|
||||
eyre!("{}", t!("registry.asset.failed-to-load-http-url")),
|
||||
ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
@@ -80,7 +80,7 @@ impl<Commitment> RegistryAsset<Commitment> {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Failed to load any http url"),
|
||||
eyre!("{}", t!("registry.asset.failed-to-load-http-url")),
|
||||
ErrorKind::Network,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ impl RegistryContext {
|
||||
};
|
||||
if config.registry_hostname.is_empty() {
|
||||
return Err(Error::new(
|
||||
eyre!("missing required configuration: registry-hostname"),
|
||||
eyre!("{}", t!("registry.context.missing-hostname")),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
}
|
||||
@@ -195,7 +195,7 @@ impl CallRemote<RegistryContext> for CliContext {
|
||||
url
|
||||
} else {
|
||||
return Err(
|
||||
Error::new(eyre!("`--registry` required"), ErrorKind::InvalidRequest).into(),
|
||||
Error::new(eyre!("{}", t!("registry.context.registry-required")), ErrorKind::InvalidRequest).into(),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -330,7 +330,7 @@ impl SignatureAuthContext for RegistryContext {
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.context.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
async fn post_auth_hook(
|
||||
&self,
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"dump",
|
||||
from_fn_async(cli_dump)
|
||||
.with_display_serializable()
|
||||
.with_about("Filter/query db to display tables and records"),
|
||||
.with_about("about.filter-query-db"),
|
||||
)
|
||||
.subcommand(
|
||||
"dump",
|
||||
@@ -34,7 +34,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"apply",
|
||||
from_fn_async(cli_apply)
|
||||
.no_display()
|
||||
.with_about("Update a db record"),
|
||||
.with_about("about.update-db-record"),
|
||||
)
|
||||
.subcommand(
|
||||
"apply",
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
|
||||
from_fn_async(get_info)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_display_serializable()
|
||||
.with_about("Display registry name, icon, and package categories")
|
||||
.with_about("about.display-registry-info")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -29,7 +29,7 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
|
||||
from_fn_async(set_name)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Set the name for the registry")
|
||||
.with_about("about.set-registry-name")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -42,7 +42,7 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
|
||||
"set-icon",
|
||||
from_fn_async(cli_set_icon)
|
||||
.no_display()
|
||||
.with_about("Set the icon for the registry"),
|
||||
.with_about("about.set-registry-icon"),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -76,26 +76,26 @@ pub fn registry_api<C: Context>() -> ParentHandler<C> {
|
||||
"index",
|
||||
from_fn_async(get_full_index)
|
||||
.with_display_serializable()
|
||||
.with_about("List info including registry name and packages")
|
||||
.with_about("about.list-registry-info-packages")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand("info", info::info_api::<C>())
|
||||
// set info and categories
|
||||
.subcommand(
|
||||
"os",
|
||||
os::os_api::<C>().with_about("Commands related to OS assets and versions"),
|
||||
os::os_api::<C>().with_about("about.commands-os-assets-versions"),
|
||||
)
|
||||
.subcommand(
|
||||
"package",
|
||||
package::package_api::<C>().with_about("Commands to index, add, or get packages"),
|
||||
package::package_api::<C>().with_about("about.commands-index-add-get-packages"),
|
||||
)
|
||||
.subcommand(
|
||||
"admin",
|
||||
admin::admin_api::<C>().with_about("Commands to add or list admins or signers"),
|
||||
admin::admin_api::<C>().with_about("about.commands-add-list-admins-signers"),
|
||||
)
|
||||
.subcommand(
|
||||
"db",
|
||||
db::db_api::<C>().with_about("Commands to interact with the db i.e. dump and apply"),
|
||||
db::db_api::<C>().with_about("about.commands-registry-db"),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ async fn add_asset(
|
||||
.mutate(|s| {
|
||||
if s.commitment != commitment {
|
||||
Err(Error::new(
|
||||
eyre!("commitment does not match"),
|
||||
eyre!("{}", t!("registry.os.asset.commitment-mismatch")),
|
||||
ErrorKind::InvalidSignature,
|
||||
))
|
||||
} else {
|
||||
@@ -154,7 +154,7 @@ async fn add_asset(
|
||||
})?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.os.asset.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await
|
||||
@@ -208,7 +208,7 @@ pub async fn cli_add_asset(
|
||||
Some("squashfs") => "squashfs",
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
eyre!("Unknown extension"),
|
||||
eyre!("{}", t!("registry.os.asset.unknown-extension")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -232,7 +232,7 @@ pub async fn cli_add_asset(
|
||||
let size = file
|
||||
.size()
|
||||
.await
|
||||
.ok_or_else(|| Error::new(eyre!("failed to read file metadata"), ErrorKind::Filesystem))?;
|
||||
.ok_or_else(|| Error::new(eyre!("{}", t!("registry.os.asset.failed-read-metadata")), ErrorKind::Filesystem))?;
|
||||
let commitment = Blake3Commitment {
|
||||
hash: Base64(*blake3.as_bytes()),
|
||||
size,
|
||||
@@ -334,7 +334,7 @@ async fn remove_asset(
|
||||
.remove(&platform)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.os.asset.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
|
||||
"iso",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download iso"),
|
||||
.with_about("about.download-iso"),
|
||||
)
|
||||
.subcommand(
|
||||
"img",
|
||||
@@ -46,7 +46,7 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
|
||||
"img",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download img"),
|
||||
.with_about("about.download-img"),
|
||||
)
|
||||
.subcommand(
|
||||
"squashfs",
|
||||
@@ -58,7 +58,7 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
|
||||
"squashfs",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download squashfs"),
|
||||
.with_about("about.download-squashfs"),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
|
||||
"add",
|
||||
from_fn_async(add::cli_add_asset)
|
||||
.no_display()
|
||||
.with_about("Add asset to registry"),
|
||||
.with_about("about.add-asset-registry"),
|
||||
)
|
||||
.subcommand("remove", add::remove_api::<C>())
|
||||
.subcommand("sign", sign::sign_api::<C>())
|
||||
@@ -19,10 +19,10 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
|
||||
"sign",
|
||||
from_fn_async(sign::cli_sign_asset)
|
||||
.no_display()
|
||||
.with_about("Sign file and add to registry index"),
|
||||
.with_about("about.sign-file-add-registry"),
|
||||
)
|
||||
.subcommand(
|
||||
"get",
|
||||
get::get_api::<C>().with_about("Commands to download image, iso, or squashfs files"),
|
||||
get::get_api::<C>().with_about("about.commands-download-assets"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ async fn sign_asset(
|
||||
.contains(&guid)
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("signer {guid} is not authorized"),
|
||||
eyre!("{}", t!("registry.os.asset.signer-not-authorized", guid = guid)),
|
||||
ErrorKind::Authorization,
|
||||
));
|
||||
}
|
||||
@@ -163,7 +163,7 @@ pub async fn cli_sign_asset(
|
||||
Some("squashfs") => "squashfs",
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
eyre!("Unknown extension"),
|
||||
eyre!("{}", t!("registry.os.asset.unknown-extension")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -186,7 +186,7 @@ pub async fn cli_sign_asset(
|
||||
let size = file
|
||||
.size()
|
||||
.await
|
||||
.ok_or_else(|| Error::new(eyre!("failed to read file metadata"), ErrorKind::Filesystem))?;
|
||||
.ok_or_else(|| Error::new(eyre!("{}", t!("registry.os.asset.failed-read-metadata")), ErrorKind::Filesystem))?;
|
||||
let commitment = Blake3Commitment {
|
||||
hash: Base64(*blake3.as_bytes()),
|
||||
size,
|
||||
|
||||
@@ -17,16 +17,16 @@ pub fn os_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(index::get_os_index)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_display_serializable()
|
||||
.with_about("List index of OS versions")
|
||||
.with_about("about.list-os-versions-index")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"asset",
|
||||
asset::asset_api::<C>().with_about("Commands to add, sign, or get registry assets"),
|
||||
asset::asset_api::<C>().with_about("about.commands-add-sign-get-assets"),
|
||||
)
|
||||
.subcommand(
|
||||
"version",
|
||||
version::version_api::<C>()
|
||||
.with_about("Commands to add, remove, or list versions or version signers"),
|
||||
.with_about("about.commands-add-remove-list-versions"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.with_metadata("get_signer", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add OS version")
|
||||
.with_about("about.add-os-version")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -35,12 +35,12 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_version)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove OS version")
|
||||
.with_about("about.remove-os-version")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"signer",
|
||||
signer::signer_api::<C>().with_about("Add, remove, and list version signers"),
|
||||
signer::signer_api::<C>().with_about("about.add-remove-list-version-signers"),
|
||||
)
|
||||
.subcommand(
|
||||
"get",
|
||||
@@ -51,7 +51,7 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
display_version_info(handle.params, result)
|
||||
})
|
||||
.with_about("Get OS versions and related version info")
|
||||
.with_about("about.get-os-versions-info")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_version_signer)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add version signer")
|
||||
.with_about("about.add-version-signer")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -29,7 +29,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_version_signer)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove version signer")
|
||||
.with_about("about.remove-version-signer")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -38,7 +38,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_display_serializable()
|
||||
.with_custom_display_fn(|handle, result| display_signers(handle.params, result))
|
||||
.with_about("List version signers and related signer info")
|
||||
.with_about("about.list-version-signers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ pub async fn remove_version_signer(
|
||||
.mutate(|s| Ok(s.remove(&signer)))?
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("signer {signer} is not authorized to sign for v{version}"),
|
||||
eyre!("{}", t!("registry.os.version.signer-not-authorized", signer = signer, version = version)),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ pub async fn add_package(
|
||||
|
||||
let Some(([url], rest)) = urls.split_at_checked(1) else {
|
||||
return Err(Error::new(
|
||||
eyre!("must specify at least 1 url"),
|
||||
eyre!("{}", t!("registry.package.add.must-specify-url")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
};
|
||||
@@ -112,7 +112,7 @@ pub async fn add_package(
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.package.add.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await
|
||||
@@ -226,7 +226,7 @@ pub async fn remove_package(
|
||||
) -> Result<bool, Error> {
|
||||
let peek = ctx.db.peek().await;
|
||||
let signer =
|
||||
signer.ok_or_else(|| Error::new(eyre!("missing signer"), ErrorKind::InvalidRequest))?;
|
||||
signer.ok_or_else(|| Error::new(eyre!("{}", t!("registry.package.missing-signer")), ErrorKind::InvalidRequest))?;
|
||||
let signer_guid = peek.as_index().as_signers().get_signer(&signer)?;
|
||||
|
||||
let rev = ctx
|
||||
@@ -267,7 +267,7 @@ pub async fn remove_package(
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.package.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await;
|
||||
@@ -342,7 +342,7 @@ pub async fn add_mirror(
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.package.add-mirror.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await
|
||||
@@ -454,7 +454,7 @@ pub async fn remove_mirror(
|
||||
) -> Result<(), Error> {
|
||||
let peek = ctx.db.peek().await;
|
||||
let signer =
|
||||
signer.ok_or_else(|| Error::new(eyre!("missing signer"), ErrorKind::InvalidRequest))?;
|
||||
signer.ok_or_else(|| Error::new(eyre!("{}", t!("registry.package.missing-signer")), ErrorKind::InvalidRequest))?;
|
||||
let signer_guid = peek.as_index().as_signers().get_signer(&signer)?;
|
||||
|
||||
ctx.db
|
||||
@@ -483,7 +483,7 @@ pub async fn remove_mirror(
|
||||
.for_each(|(_, asset)| asset.urls.retain(|u| u != &url));
|
||||
if s.iter().any(|(_, asset)| asset.urls.is_empty()) {
|
||||
Err(Error::new(
|
||||
eyre!("cannot remove last mirror from an s9pk"),
|
||||
eyre!("{}", t!("registry.package.cannot-remove-last-mirror")),
|
||||
ErrorKind::InvalidRequest,
|
||||
))
|
||||
} else {
|
||||
@@ -493,7 +493,7 @@ pub async fn remove_mirror(
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||
Err(Error::new(eyre!("{}", t!("registry.package.remove-mirror.unauthorized")), ErrorKind::Authorization))
|
||||
}
|
||||
})
|
||||
.await
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_category)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a category to the registry")
|
||||
.with_about("about.add-category-registry")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -28,7 +28,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_category)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a category from the registry")
|
||||
.with_about("about.remove-category-registry")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -36,7 +36,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_package)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a package to a category")
|
||||
.with_about("about.add-package-category")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -44,7 +44,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_package)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a package from a category")
|
||||
.with_about("about.remove-package-category")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
|
||||
@@ -441,8 +441,8 @@ pub async fn cli_download(
|
||||
0 => {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Could not find a version of {id} that satisfies {}",
|
||||
target_version.unwrap_or(VersionRange::Any)
|
||||
"{}",
|
||||
t!("registry.package.get.version-not-found", id = id, version = target_version.unwrap_or(VersionRange::Any))
|
||||
),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
@@ -462,8 +462,8 @@ pub async fn cli_download(
|
||||
0 => {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Could not find a version of {id} that satisfies {}",
|
||||
target_version.unwrap_or(VersionRange::Any)
|
||||
"{}",
|
||||
t!("registry.package.get.version-not-found", id = id, version = target_version.unwrap_or(VersionRange::Any))
|
||||
),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
@@ -551,7 +551,7 @@ pub async fn cli_download(
|
||||
progress_tracker.complete();
|
||||
progress.await.unwrap();
|
||||
|
||||
println!("Download Complete");
|
||||
println!("{}", t!("registry.package.get.download-complete"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(index::get_package_index)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.with_display_serializable()
|
||||
.with_about("List packages and categories")
|
||||
.with_about("about.list-packages-categories")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -30,7 +30,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
"add",
|
||||
from_fn_async(add::cli_add_package)
|
||||
.no_display()
|
||||
.with_about("Add package to registry index"),
|
||||
.with_about("about.add-package-registry"),
|
||||
)
|
||||
.subcommand(
|
||||
"add-mirror",
|
||||
@@ -42,7 +42,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
"add-mirror",
|
||||
from_fn_async(add::cli_add_mirror)
|
||||
.no_display()
|
||||
.with_about("Add a mirror for an s9pk"),
|
||||
.with_about("about.add-mirror-s9pk"),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
@@ -51,17 +51,17 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|args, changed| {
|
||||
if !changed {
|
||||
tracing::warn!(
|
||||
"{}@{}{} does not exist, so not removed",
|
||||
args.params.id,
|
||||
args.params.version,
|
||||
args.params
|
||||
.sighash
|
||||
.map_or(String::new(), |h| format!("#{h}"))
|
||||
"{}",
|
||||
t!("registry.package.remove-not-exist",
|
||||
id = args.params.id,
|
||||
version = args.params.version,
|
||||
sighash = args.params.sighash.map_or(String::new(), |h| format!("#{h}"))
|
||||
)
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Remove package from registry index")
|
||||
.with_about("about.remove-package-registry")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -69,12 +69,12 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add::remove_mirror)
|
||||
.with_metadata("get_signer", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a mirror from a package")
|
||||
.with_about("about.remove-mirror-package")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"signer",
|
||||
signer::signer_api::<C>().with_about("Add, remove, and list package signers"),
|
||||
signer::signer_api::<C>().with_about("about.add-remove-list-package-signers"),
|
||||
)
|
||||
.subcommand(
|
||||
"get",
|
||||
@@ -85,18 +85,18 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
get::display_package_info(handle.params, result)
|
||||
})
|
||||
.with_about("List installation candidate package(s)")
|
||||
.with_about("about.list-installation-candidates")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"download",
|
||||
from_fn_async_local(get::cli_download)
|
||||
.no_display()
|
||||
.with_about("Download an s9pk"),
|
||||
.with_about("about.download-s9pk"),
|
||||
)
|
||||
.subcommand(
|
||||
"category",
|
||||
category::category_api::<C>()
|
||||
.with_about("Update the categories for packages on the registry"),
|
||||
.with_about("about.update-categories-registry"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_package_signer)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add package signer")
|
||||
.with_about("about.add-package-signer")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -30,7 +30,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_package_signer)
|
||||
.with_metadata("admin", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove package signer")
|
||||
.with_about("about.remove-package-signer")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -41,7 +41,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
display_package_signers(handle.params, result)
|
||||
})
|
||||
.with_about("List package signers and related signer info")
|
||||
.with_about("about.list-package-signers")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -114,7 +114,7 @@ pub async fn remove_package_signer(
|
||||
.is_some()
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("signer {signer} is not authorized to sign for {id}"),
|
||||
eyre!("{}", t!("registry.package.signer.not-authorized", signer = signer, id = id)),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ impl AcceptSigners {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("signer(s) not accepted"),
|
||||
eyre!("{}", t!("registry.signer.not-accepted")),
|
||||
ErrorKind::InvalidSignature,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ pub fn s9pk() -> ParentHandler<CliContext> {
|
||||
"pack",
|
||||
from_fn_async(super::v2::pack::pack)
|
||||
.no_display()
|
||||
.with_about("Package s9pk input files into valid s9pk"),
|
||||
.with_about("about.package-s9pk-input-files-into-valid-s9pk"),
|
||||
)
|
||||
.subcommand(
|
||||
"list-ingredients",
|
||||
@@ -45,21 +45,21 @@ pub fn s9pk() -> ParentHandler<CliContext> {
|
||||
println!();
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List paths of package ingredients"),
|
||||
.with_about("about.list-paths-of-package-ingredients"),
|
||||
)
|
||||
.subcommand(
|
||||
"edit",
|
||||
edit().with_about("Commands to add an image to an s9pk or edit the manifest"),
|
||||
edit().with_about("about.commands-add-image-or-edit-manifest"),
|
||||
)
|
||||
.subcommand(
|
||||
"inspect",
|
||||
inspect().with_about("Commands to display file paths, file contents, or manifest"),
|
||||
inspect().with_about("about.commands-display-file-paths-contents-manifest"),
|
||||
)
|
||||
.subcommand(
|
||||
"convert",
|
||||
from_fn_async(convert)
|
||||
.no_display()
|
||||
.with_about("Convert s9pk from v1 to v2"),
|
||||
.with_about("about.convert-s9pk-v1-to-v2"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -76,14 +76,14 @@ fn edit() -> ParentHandler<CliContext, S9pkPath> {
|
||||
from_fn_async(add_image)
|
||||
.with_inherited(only_parent)
|
||||
.no_display()
|
||||
.with_about("Add image to s9pk"),
|
||||
.with_about("about.add-image-to-s9pk"),
|
||||
)
|
||||
.subcommand(
|
||||
"manifest",
|
||||
from_fn_async(edit_manifest)
|
||||
.with_inherited(only_parent)
|
||||
.with_display_serializable()
|
||||
.with_about("Edit s9pk manifest"),
|
||||
.with_about("about.edit-s9pk-manifest"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,21 +95,21 @@ fn inspect() -> ParentHandler<CliContext, S9pkPath> {
|
||||
from_fn_async(file_tree)
|
||||
.with_inherited(only_parent)
|
||||
.with_display_serializable()
|
||||
.with_about("Display list of paths"),
|
||||
.with_about("about.display-list-of-paths"),
|
||||
)
|
||||
.subcommand(
|
||||
"cat",
|
||||
from_fn_async(cat)
|
||||
.with_inherited(only_parent)
|
||||
.no_display()
|
||||
.with_about("Display file contents"),
|
||||
.with_about("about.display-file-contents"),
|
||||
)
|
||||
.subcommand(
|
||||
"manifest",
|
||||
from_fn_async(inspect_manifest)
|
||||
.with_inherited(only_parent)
|
||||
.with_display_serializable()
|
||||
.with_about("Display s9pk manifest"),
|
||||
.with_about("about.display-s9pk-manifest"),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ pub fn update_tasks(
|
||||
}
|
||||
}
|
||||
None => {
|
||||
tracing::error!("action request exists in an invalid state {:?}", v.task);
|
||||
tracing::error!("{}", t!("service.action.action-request-invalid-state", task = format!("{:?}", v.task)));
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -151,7 +151,7 @@ impl Handler<RunAction> for ServiceActor {
|
||||
.de()?;
|
||||
if matches!(&action.visibility, ActionVisibility::Disabled(_)) {
|
||||
return Err(Error::new(
|
||||
eyre!("action {action_id} is disabled"),
|
||||
eyre!("{}", t!("service.action.action-is-disabled", action_id = action_id)),
|
||||
ErrorKind::Action,
|
||||
));
|
||||
}
|
||||
@@ -162,7 +162,7 @@ impl Handler<RunAction> for ServiceActor {
|
||||
_ => false,
|
||||
} {
|
||||
return Err(Error::new(
|
||||
eyre!("service is not in allowed status for {action_id}"),
|
||||
eyre!("{}", t!("service.action.service-not-in-allowed-status", action_id = action_id)),
|
||||
ErrorKind::Action,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::action::{ActionInput, ActionResult, display_action_result};
|
||||
use crate::db::model::package::{
|
||||
@@ -175,7 +176,7 @@ async fn run_action(
|
||||
|
||||
if package_id != &context.seed.id {
|
||||
return Err(Error::new(
|
||||
eyre!("calling actions on other packages is unsupported at this time"),
|
||||
eyre!("{}", t!("service.effects.action.calling-actions-on-other-packages-unsupported")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
context
|
||||
@@ -220,7 +221,7 @@ async fn create_task(
|
||||
TaskCondition::InputNotMatches => {
|
||||
let Some(input) = task.input.as_ref() else {
|
||||
return Err(Error::new(
|
||||
eyre!("input-not-matches trigger requires input to be specified"),
|
||||
eyre!("{}", t!("service.effects.action.input-not-matches-requires-input")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
};
|
||||
@@ -238,9 +239,7 @@ async fn create_task(
|
||||
else {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"action {} of {} has no input",
|
||||
task.action_id,
|
||||
task.package_id
|
||||
"{}", t!("service.effects.action.action-has-no-input", action_id = task.action_id, package_id = task.package_id)
|
||||
),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::str::FromStr;
|
||||
use clap::builder::ValueParserFactory;
|
||||
use exver::VersionRange;
|
||||
use imbl_value::InternedString;
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::db::model::package::{
|
||||
CurrentDependencies, CurrentDependencyInfo, CurrentDependencyKind, ManifestPreference,
|
||||
@@ -148,13 +149,13 @@ impl FromStr for DependencyRequirement {
|
||||
.map(|id| id.parse().map_err(Error::from))
|
||||
.collect(),
|
||||
Some((kind, _)) => Err(Error::new(
|
||||
eyre!("unknown dependency kind {kind}"),
|
||||
eyre!("{}", t!("service.effects.dependency.unknown-dependency-kind", kind = kind)),
|
||||
ErrorKind::InvalidRequest,
|
||||
)),
|
||||
None => match rest {
|
||||
"r" | "running" => Ok(BTreeSet::new()),
|
||||
kind => Err(Error::new(
|
||||
eyre!("unknown dependency kind {kind}"),
|
||||
eyre!("{}", t!("service.effects.dependency.unknown-dependency-kind", kind = kind)),
|
||||
ErrorKind::InvalidRequest,
|
||||
)),
|
||||
},
|
||||
|
||||
@@ -28,6 +28,7 @@ use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
|
||||
use ts_rs::TS;
|
||||
use url::Url;
|
||||
|
||||
|
||||
use crate::context::{CliContext, RpcContext};
|
||||
use crate::db::model::package::{
|
||||
InstalledState, ManifestPreference, PackageState, PackageStateMatchModelRef, TaskSeverity,
|
||||
@@ -172,7 +173,7 @@ impl ServiceRef {
|
||||
}
|
||||
let service = Arc::try_unwrap(self.0).map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("ServiceActor held somewhere after actor shutdown"),
|
||||
eyre!("{}", t!("service.mod.service-actor-held-after-shutdown")),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
})?;
|
||||
@@ -183,7 +184,7 @@ impl ServiceRef {
|
||||
Arc::try_unwrap(service.seed)
|
||||
.map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("ServiceActorSeed held somewhere after actor shutdown"),
|
||||
eyre!("{}", t!("service.mod.service-actor-seed-held-after-shutdown")),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
})?
|
||||
@@ -375,7 +376,7 @@ impl Service {
|
||||
{
|
||||
Ok(PackageState::Installed(InstalledState { manifest }))
|
||||
} else {
|
||||
Err(Error::new(eyre!("Race condition detected - package state changed during load"), ErrorKind::Database))
|
||||
Err(Error::new(eyre!("{}", t!("service.mod.race-condition-detected")), ErrorKind::Database))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -446,7 +447,7 @@ impl Service {
|
||||
handle_installed(S9pk::open(s9pk_path, Some(id)).await?).await
|
||||
}
|
||||
PackageStateMatchModelRef::Error(e) => Err(Error::new(
|
||||
eyre!("Failed to parse PackageDataEntry, found {e:?}"),
|
||||
eyre!("{}", t!("service.mod.failed-to-parse-package-data-entry", error = format!("{e:?}"))),
|
||||
ErrorKind::Deserialization,
|
||||
)),
|
||||
}
|
||||
@@ -552,7 +553,7 @@ impl Service {
|
||||
true
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"Deleting task {id} because action no longer exists"
|
||||
"{}", t!("service.mod.deleting-task-action-no-longer-exists", id = id)
|
||||
);
|
||||
false
|
||||
}
|
||||
@@ -789,7 +790,7 @@ pub async fn attach(
|
||||
.join("\n");
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"no matching subcontainers are running for {id}; some possible choices are:\n{subcontainers}"
|
||||
"{}", t!("service.mod.no-matching-subcontainers", id = id, subcontainers = subcontainers)
|
||||
),
|
||||
ErrorKind::NotFound,
|
||||
));
|
||||
@@ -828,7 +829,7 @@ pub async fn attach(
|
||||
.map(format_subcontainer_pair)
|
||||
.join("\n");
|
||||
return Err(Error::new(
|
||||
eyre!("multiple subcontainers found for {id}: \n{subcontainer_ids}"),
|
||||
eyre!("{}", t!("service.mod.multiple-subcontainers-found", id = id, subcontainer_ids = subcontainer_ids)),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -985,7 +986,7 @@ pub async fn attach(
|
||||
"signal" => {
|
||||
if data.len() != 4 {
|
||||
return Err(Error::new(
|
||||
eyre!("invalid byte length for signal: {}", data.len()),
|
||||
eyre!("{}", t!("service.mod.invalid-byte-length-for-signal", length = data.len())),
|
||||
ErrorKind::InvalidRequest
|
||||
));
|
||||
}
|
||||
@@ -1118,14 +1119,14 @@ async fn get_passwd_command(etc_passwd_path: PathBuf, user: &str) -> RootCommand
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Could not parse /etc/passwd for shell: {}", contents),
|
||||
eyre!("{}", t!("service.mod.could-not-parse-etc-passwd", contents = contents)),
|
||||
ErrorKind::Filesystem,
|
||||
))
|
||||
}
|
||||
.await
|
||||
.map(RootCommand)
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::error!("Could not get the /etc/passwd: {e}");
|
||||
tracing::error!("{}", t!("service.mod.could-not-get-etc-passwd", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
RootCommand("/bin/sh".to_string())
|
||||
})
|
||||
@@ -1287,7 +1288,7 @@ pub async fn cli_attach(
|
||||
"exit" => {
|
||||
if data.len() != 4 {
|
||||
return Err(Error::new(
|
||||
eyre!("invalid byte length for exit code: {}", data.len()),
|
||||
eyre!("{}", t!("service.mod.invalid-byte-length-for-exit-code", length = data.len())),
|
||||
ErrorKind::InvalidRequest
|
||||
));
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ impl PersistentContainer {
|
||||
.get()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("PersistentContainer has been destroyed"),
|
||||
eyre!("{}", t!("service.persistent-container.container-destroyed")),
|
||||
ErrorKind::Incoherent,
|
||||
)
|
||||
})?
|
||||
@@ -354,7 +354,7 @@ impl PersistentContainer {
|
||||
.get()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("PersistentContainer has been destroyed"),
|
||||
eyre!("{}", t!("service.persistent-container.container-destroyed")),
|
||||
ErrorKind::Incoherent,
|
||||
)
|
||||
})?
|
||||
@@ -364,7 +364,7 @@ impl PersistentContainer {
|
||||
let handle = NonDetachingJoinHandle::from(tokio::spawn(async move {
|
||||
let chown_status = async {
|
||||
let res = server.run_unix(&path, |err| {
|
||||
tracing::error!("error on unix socket {}: {err}", path.display())
|
||||
tracing::error!("{}", t!("service.persistent-container.error-on-unix-socket", path = path.display(), error = err))
|
||||
})?;
|
||||
Command::new("chown")
|
||||
.arg("100000:100000")
|
||||
@@ -386,7 +386,7 @@ impl PersistentContainer {
|
||||
}));
|
||||
let shutdown = recv.await.map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("unix socket server thread panicked"),
|
||||
eyre!("{}", t!("service.persistent-container.unix-socket-server-panicked")),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
})??;
|
||||
@@ -396,7 +396,7 @@ impl PersistentContainer {
|
||||
.is_some()
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!("PersistentContainer already initialized"),
|
||||
eyre!("{}", t!("service.persistent-container.already-initialized")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -473,7 +473,7 @@ impl PersistentContainer {
|
||||
if let Some(destroy) = self.destroy(uninit) {
|
||||
destroy.await?;
|
||||
}
|
||||
tracing::info!("Service for {} exited", self.s9pk.as_manifest().id);
|
||||
tracing::info!("{}", t!("service.persistent-container.service-exited", id = self.s9pk.as_manifest().id));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@ impl Actor for ServiceActor {
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("error synchronizing state of service: {e}");
|
||||
tracing::error!("{}", t!("service.service-actor.error-synchronizing-state", error = e));
|
||||
tracing::debug!("{e:?}");
|
||||
tracing::error!("Retrying in {}s...", SYNC_RETRY_COOLDOWN_SECONDS);
|
||||
tracing::error!("{}", t!("service.service-actor.retrying-in-seconds", seconds = SYNC_RETRY_COOLDOWN_SECONDS));
|
||||
tokio::time::timeout(
|
||||
Duration::from_secs(SYNC_RETRY_COOLDOWN_SECONDS),
|
||||
async {
|
||||
|
||||
@@ -25,7 +25,7 @@ impl ServiceActorSeed {
|
||||
fut.await.map_err(Error::from)
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("No backup to resume"),
|
||||
eyre!("{}", t!("service.transition.backup.no-backup-to-resume")),
|
||||
ErrorKind::Cancelled,
|
||||
))
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ pub async fn cleanup(ctx: &RpcContext, id: &PackageId, soft: bool) -> Result<(),
|
||||
| PackageState::Removing(InstalledState { manifest }) => manifest,
|
||||
s => {
|
||||
return Err(Error::new(
|
||||
eyre!("Invalid package state for cleanup: {s:?}"),
|
||||
eyre!("{}", t!("service.uninstall.invalid-package-state-for-cleanup", state = format!("{s:?}"))),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ pub async fn attach(
|
||||
let setup_ctx = ctx.clone();
|
||||
ctx.run_setup(move || async move {
|
||||
let progress = &setup_ctx.progress;
|
||||
let mut disk_phase = progress.add_phase("Opening data drive".into(), Some(10));
|
||||
let mut disk_phase = progress.add_phase(t!("setup.opening-data-drive").into(), Some(10));
|
||||
let init_phases = InitPhases::new(&progress);
|
||||
let rpc_ctx_phases = InitRpcContextPhases::new(&progress);
|
||||
|
||||
@@ -163,7 +163,7 @@ pub async fn attach(
|
||||
a @ Some(_) => a,
|
||||
None => {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("Couldn't decode password"),
|
||||
color_eyre::eyre::eyre!("{}", t!("setup.couldnt-decode-password")),
|
||||
crate::ErrorKind::Unknown,
|
||||
));
|
||||
}
|
||||
@@ -192,9 +192,7 @@ pub async fn attach(
|
||||
if requires_reboot.0 {
|
||||
crate::disk::main::export(&*disk_guid, DATA_DIR).await?;
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Errors were corrected with your disk, but the server must be restarted in order to proceed"
|
||||
),
|
||||
eyre!("{}", t!("setup.disk-errors-corrected-restart-required")),
|
||||
ErrorKind::DiskManagement,
|
||||
));
|
||||
}
|
||||
@@ -313,7 +311,7 @@ pub async fn verify_cifs(
|
||||
guard.unmount().await?;
|
||||
if start_os.is_empty() {
|
||||
return Err(Error::new(
|
||||
eyre!("No Backup Found"),
|
||||
eyre!("{}", t!("setup.no-backup-found")),
|
||||
crate::ErrorKind::NotFound,
|
||||
));
|
||||
}
|
||||
@@ -382,7 +380,7 @@ pub async fn execute(
|
||||
Some(a) => a,
|
||||
None => {
|
||||
return Err(Error::new(
|
||||
color_eyre::eyre::eyre!("Couldn't decode startOsPassword"),
|
||||
color_eyre::eyre::eyre!("{}", t!("setup.couldnt-decode-startos-password")),
|
||||
crate::ErrorKind::Unknown,
|
||||
));
|
||||
}
|
||||
@@ -396,7 +394,7 @@ pub async fn execute(
|
||||
target,
|
||||
password: password.decrypt(&ctx).ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Couldn't decode recoveryPassword"),
|
||||
color_eyre::eyre::eyre!("{}", t!("setup.couldnt-decode-recovery-password")),
|
||||
crate::ErrorKind::Unknown,
|
||||
)
|
||||
})?,
|
||||
@@ -439,7 +437,7 @@ pub async fn complete(ctx: SetupContext) -> Result<SetupResult, Error> {
|
||||
}
|
||||
Some(Err(e)) => Err(e.clone_output()),
|
||||
None => Err(Error::new(
|
||||
eyre!("setup.execute has not completed successfully"),
|
||||
eyre!("{}", t!("setup.execute-not-completed")),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
)),
|
||||
}
|
||||
@@ -471,13 +469,13 @@ pub async fn execute_inner(
|
||||
kiosk: Option<bool>,
|
||||
) -> Result<(SetupResult, RpcContext), Error> {
|
||||
let progress = &ctx.progress;
|
||||
let mut disk_phase = progress.add_phase("Formatting data drive".into(), Some(10));
|
||||
let mut disk_phase = progress.add_phase(t!("setup.formatting-data-drive").into(), Some(10));
|
||||
let restore_phase = match recovery_source.as_ref() {
|
||||
Some(RecoverySource::Backup { .. }) => {
|
||||
Some(progress.add_phase("Restoring backup".into(), Some(100)))
|
||||
Some(progress.add_phase(t!("setup.restoring-backup").into(), Some(100)))
|
||||
}
|
||||
Some(RecoverySource::Migrate { .. }) => {
|
||||
Some(progress.add_phase("Transferring data".into(), Some(100)))
|
||||
Some(progress.add_phase(t!("setup.transferring-data").into(), Some(100)))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
use crate::PLATFORM;
|
||||
use crate::context::RpcContext;
|
||||
use crate::disk::main::export;
|
||||
@@ -17,9 +18,9 @@ impl Shutdown {
|
||||
use std::process::Command;
|
||||
|
||||
if self.restart {
|
||||
tracing::info!("Beginning server restart");
|
||||
tracing::info!("{}", t!("shutdown.beginning-restart"));
|
||||
} else {
|
||||
tracing::info!("Beginning server shutdown");
|
||||
tracing::info!("{}", t!("shutdown.beginning-shutdown"));
|
||||
}
|
||||
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
@@ -35,18 +36,18 @@ impl Shutdown {
|
||||
.invoke(crate::ErrorKind::Journald)
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error Stopping Journald: {}", e);
|
||||
tracing::error!("{}", t!("shutdown.error-stopping-journald", error = e.to_string()));
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
if let Some(guid) = &self.disk_guid {
|
||||
if let Err(e) = export(guid, crate::DATA_DIR).await {
|
||||
tracing::error!("Error Exporting Volume Group: {}", e);
|
||||
tracing::error!("{}", t!("shutdown.error-exporting-volume-group", error = e.to_string()));
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
if &*PLATFORM != "raspberrypi" || self.restart {
|
||||
if let Err(e) = SHUTDOWN.play().await {
|
||||
tracing::error!("Error Playing Shutdown Song: {}", e);
|
||||
tracing::error!("{}", t!("shutdown.error-playing-shutdown-song", error = e.to_string()));
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +92,14 @@ pub fn ssh<C: Context>() -> ParentHandler<C> {
|
||||
"add",
|
||||
from_fn_async(add)
|
||||
.no_display()
|
||||
.with_about("Add ssh key")
|
||||
.with_about("about.add-ssh-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"remove",
|
||||
from_fn_async(remove)
|
||||
.no_display()
|
||||
.with_about("Remove ssh key")
|
||||
.with_about("about.remove-ssh-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -109,7 +109,7 @@ pub fn ssh<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
display_all_ssh_keys(handle.params, result)
|
||||
})
|
||||
.with_about("List ssh keys")
|
||||
.with_about("about.list-ssh-keys")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -168,7 +168,10 @@ pub async fn remove(
|
||||
if keys_ref.remove(&fingerprint)?.is_some() {
|
||||
keys_ref.de()
|
||||
} else {
|
||||
Err(Error::new(eyre!("SSH Key Not Found"), ErrorKind::NotFound))
|
||||
Err(Error::new(
|
||||
eyre!("{}", t!("ssh.key-not-found")),
|
||||
ErrorKind::NotFound,
|
||||
))
|
||||
}
|
||||
})
|
||||
.await
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn experimental<C: Context>() -> ParentHandler<C> {
|
||||
"zram",
|
||||
from_fn_async(zram)
|
||||
.no_display()
|
||||
.with_about("Enable zram")
|
||||
.with_about("about.enable-zram")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -44,7 +44,7 @@ pub fn experimental<C: Context>() -> ParentHandler<C> {
|
||||
.with_custom_display_fn(|handle, result| {
|
||||
display_governor_info(handle.params, result)
|
||||
})
|
||||
.with_about("Show current and available CPU governors")
|
||||
.with_about("about.show-cpu-governors")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -159,7 +159,10 @@ pub async fn governor(
|
||||
if let Some(set) = set {
|
||||
if !available.contains(&set) {
|
||||
return Err(Error::new(
|
||||
eyre!("Governor {set} not available"),
|
||||
eyre!(
|
||||
"{}",
|
||||
t!("system.governor-not-available", governor = set.to_string())
|
||||
),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -295,7 +298,7 @@ pub fn kiosk<C: Context>() -> ParentHandler<C> {
|
||||
enable_kiosk().await
|
||||
})
|
||||
.no_display()
|
||||
.with_about("Enable kiosk mode")
|
||||
.with_about("about.enable-kiosk-mode")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -313,7 +316,7 @@ pub fn kiosk<C: Context>() -> ParentHandler<C> {
|
||||
disable_kiosk().await
|
||||
})
|
||||
.no_display()
|
||||
.with_about("Disable kiosk mode")
|
||||
.with_about("about.disable-kiosk-mode")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -553,7 +556,13 @@ pub async fn launch_metrics_task<F: FnMut() -> Receiver<Option<Shutdown>>>(
|
||||
let init_temp = match get_temp().await {
|
||||
Ok(a) => Some(a),
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get initial temperature: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-initial-temperature",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
None
|
||||
}
|
||||
@@ -570,12 +579,24 @@ pub async fn launch_metrics_task<F: FnMut() -> Receiver<Option<Shutdown>>>(
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get initial cpu info: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-initial-cpu-info",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get initial proc stat: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-initial-proc-stat",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -590,7 +611,13 @@ pub async fn launch_metrics_task<F: FnMut() -> Receiver<Option<Shutdown>>>(
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get initial mem info: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-initial-mem-info",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -605,7 +632,13 @@ pub async fn launch_metrics_task<F: FnMut() -> Receiver<Option<Shutdown>>>(
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get initial disk info: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-initial-disk-info",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -650,7 +683,13 @@ async fn launch_temp_task(
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get new temperature: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-new-temperature",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -673,7 +712,13 @@ async fn launch_cpu_task(
|
||||
cache.send_modify(|c| c.as_mut().unwrap().cpu = info);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get new CPU Metrics: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-new-cpu-metrics",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -692,7 +737,13 @@ async fn launch_mem_task(cache: &Watch<Option<Metrics>>, mut shutdown: Receiver<
|
||||
cache.send_modify(|c| c.as_mut().unwrap().memory = a);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get new Memory Metrics: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-new-memory-metrics",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -721,7 +772,13 @@ async fn launch_disk_task(
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Could not get new Disk Metrics: {}", e);
|
||||
tracing::error!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.could-not-get-new-disk-metrics",
|
||||
error = e.to_string()
|
||||
)
|
||||
);
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -757,7 +814,12 @@ async fn get_temp() -> Result<Celsius, Error> {
|
||||
}
|
||||
})
|
||||
.reduce(f64::max)
|
||||
.ok_or_else(|| Error::new(eyre!("No temperatures available"), ErrorKind::Filesystem))?;
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("{}", t!("system.no-temperatures-available")),
|
||||
ErrorKind::Filesystem,
|
||||
)
|
||||
})?;
|
||||
Ok(Celsius(temp))
|
||||
}
|
||||
|
||||
@@ -803,7 +865,10 @@ async fn get_proc_stat() -> Result<ProcStat, Error> {
|
||||
.map(|s| {
|
||||
s.parse::<u64>().map_err(|e| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!("Invalid /proc/stat column value: {}", e),
|
||||
color_eyre::eyre::eyre!(
|
||||
"{}",
|
||||
t!("system.invalid-proc-stat-column", error = e.to_string())
|
||||
),
|
||||
ErrorKind::ParseSysInfo,
|
||||
)
|
||||
})
|
||||
@@ -813,8 +878,8 @@ async fn get_proc_stat() -> Result<ProcStat, Error> {
|
||||
if stats.len() < 10 {
|
||||
Err(Error::new(
|
||||
eyre!(
|
||||
"Columns missing from /proc/stat. Need 10, found {}",
|
||||
stats.len()
|
||||
"{}",
|
||||
t!("system.columns-missing-from-proc-stat", count = stats.len())
|
||||
),
|
||||
ErrorKind::ParseSysInfo,
|
||||
))
|
||||
@@ -872,16 +937,22 @@ pub async fn get_mem_info() -> Result<MetricsMemory, Error> {
|
||||
zram_free: None,
|
||||
};
|
||||
fn get_num_kb(l: &str) -> Result<u64, Error> {
|
||||
let e = Error::new(
|
||||
color_eyre::eyre::eyre!("Invalid meminfo line: {}", l),
|
||||
ErrorKind::ParseSysInfo,
|
||||
);
|
||||
let line = l.to_string();
|
||||
let e = || {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!(
|
||||
"{}",
|
||||
t!("system.invalid-meminfo-line", line = line.clone())
|
||||
),
|
||||
ErrorKind::ParseSysInfo,
|
||||
)
|
||||
};
|
||||
match l.split_whitespace().skip(1).next() {
|
||||
Some(x) => match x.parse() {
|
||||
Ok(y) => Ok(y),
|
||||
Err(_) => Err(e),
|
||||
Err(_) => Err(e()),
|
||||
},
|
||||
None => Err(e),
|
||||
None => Err(e()),
|
||||
}
|
||||
}
|
||||
for entry in contents.lines() {
|
||||
@@ -900,10 +971,19 @@ pub async fn get_mem_info() -> Result<MetricsMemory, Error> {
|
||||
}
|
||||
}
|
||||
fn ensure_present(a: Option<u64>, field: &str) -> Result<u64, Error> {
|
||||
a.ok_or(Error::new(
|
||||
color_eyre::eyre::eyre!("{} missing from /proc/meminfo", field),
|
||||
ErrorKind::ParseSysInfo,
|
||||
))
|
||||
let field_str = field.to_string();
|
||||
a.ok_or_else(|| {
|
||||
Error::new(
|
||||
color_eyre::eyre::eyre!(
|
||||
"{}",
|
||||
t!(
|
||||
"system.field-missing-from-meminfo",
|
||||
field = field_str.clone()
|
||||
)
|
||||
),
|
||||
ErrorKind::ParseSysInfo,
|
||||
)
|
||||
})
|
||||
}
|
||||
let mem_total = ensure_present(mem_info.mem_total, "MemTotal")?;
|
||||
let mem_free = ensure_present(mem_info.mem_free, "MemFree")?;
|
||||
@@ -1136,7 +1216,7 @@ pub async fn set_language(
|
||||
.await?;
|
||||
write_file_atomic(
|
||||
"/media/startos/config/overlay/etc/default/locale",
|
||||
format!("{language}.UTF-8\n").as_bytes(),
|
||||
format!("LANG={language}.UTF-8\n").as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
ctx.db
|
||||
|
||||
@@ -20,19 +20,19 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"db",
|
||||
super::db::db_api::<C>()
|
||||
.with_about("Commands to interact with the db i.e. dump and apply"),
|
||||
.with_about("about.commands-interact-with-db-dump-apply"),
|
||||
)
|
||||
.subcommand(
|
||||
"auth",
|
||||
super::auth::auth_api::<C>().with_about("Add or remove authorized clients"),
|
||||
super::auth::auth_api::<C>().with_about("about.add-or-remove-authorized-clients"),
|
||||
)
|
||||
.subcommand(
|
||||
"subnet",
|
||||
subnet_api::<C>().with_about("Add, remove, or modify subnets"),
|
||||
subnet_api::<C>().with_about("about.add-remove-or-modify-subnets"),
|
||||
)
|
||||
.subcommand(
|
||||
"device",
|
||||
device_api::<C>().with_about("Add, remove, or list devices in subnets"),
|
||||
device_api::<C>().with_about("about.add-remove-or-list-devices-in-subnets"),
|
||||
)
|
||||
.subcommand(
|
||||
"port-forward",
|
||||
@@ -42,7 +42,7 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_forward)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a new port forward")
|
||||
.with_about("about.add-new-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -50,7 +50,7 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_forward)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a port forward")
|
||||
.with_about("about.remove-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
),
|
||||
)
|
||||
@@ -70,7 +70,7 @@ pub fn subnet_api<C: Context>() -> ParentHandler<C, SubnetParams> {
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|a, _| a)
|
||||
.no_display()
|
||||
.with_about("Add a new subnet")
|
||||
.with_about("about.add-new-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -79,7 +79,7 @@ pub fn subnet_api<C: Context>() -> ParentHandler<C, SubnetParams> {
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|a, _| a)
|
||||
.no_display()
|
||||
.with_about("Remove a subnet")
|
||||
.with_about("about.remove-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_device)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a device to a subnet")
|
||||
.with_about("about.add-device-to-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -99,7 +99,7 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_device)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a device from a subnet")
|
||||
.with_about("about.remove-device-from-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -123,13 +123,13 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List devices in a subnet")
|
||||
.with_about("about.list-devices-in-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"show-config",
|
||||
from_fn_async(show_config)
|
||||
.with_about("Show the WireGuard configuration for a device")
|
||||
.with_about("about.show-wireguard-configuration-for-device")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -129,13 +129,13 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"set-password",
|
||||
from_fn_async(set_password_cli)
|
||||
.with_about("Set user interface password")
|
||||
.with_about("about.set-user-interface-password")
|
||||
.no_display(),
|
||||
)
|
||||
.subcommand(
|
||||
"reset-password",
|
||||
from_fn_async(reset_password)
|
||||
.with_about("Reset user interface password")
|
||||
.with_about("about.reset-user-interface-password")
|
||||
.no_display(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -146,7 +146,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_key)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a new authorized key")
|
||||
.with_about("about.add-new-authorized-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -154,7 +154,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_key)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove an authorized key")
|
||||
.with_about("about.remove-authorized-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -175,7 +175,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
table.print_tty(false)?;
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List authorized keys")
|
||||
.with_about("about.list-authorized-keys")
|
||||
.with_call_remote::<CliContext>(),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"dump",
|
||||
from_fn_async(cli_dump)
|
||||
.with_display_serializable()
|
||||
.with_about("Filter/query db to display tables and records"),
|
||||
.with_about("about.filter-query-db-display-tables-records"),
|
||||
)
|
||||
.subcommand(
|
||||
"dump",
|
||||
@@ -107,7 +107,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"apply",
|
||||
from_fn_async(cli_apply)
|
||||
.no_display()
|
||||
.with_about("Update a db record"),
|
||||
.with_about("about.update-db-record"),
|
||||
)
|
||||
.subcommand(
|
||||
"apply",
|
||||
|
||||
@@ -98,27 +98,27 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
"init",
|
||||
from_fn_async_local(init_web)
|
||||
.no_display()
|
||||
.with_about("Initialize the webserver"),
|
||||
.with_about("about.initialize-webserver"),
|
||||
)
|
||||
.subcommand(
|
||||
"set-listen",
|
||||
from_fn_async(set_listen)
|
||||
.no_display()
|
||||
.with_about("Set the listen address for the webserver")
|
||||
.with_about("about.set-listen-address-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-listen",
|
||||
from_fn_async(get_listen)
|
||||
.with_display_serializable()
|
||||
.with_about("Get the listen address for the webserver")
|
||||
.with_about("about.get-listen-address-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-available-ips",
|
||||
from_fn_async(get_available_ips)
|
||||
.with_display_serializable()
|
||||
.with_about("Get available IP addresses to bind to")
|
||||
.with_about("about.get-available-ip-addresses-to-bind")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -129,12 +129,12 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
"import-certificate",
|
||||
from_fn_async_local(import_certificate_cli)
|
||||
.no_display()
|
||||
.with_about("Import a certificate to use for the webserver"),
|
||||
.with_about("about.import-certificate-for-webserver"),
|
||||
)
|
||||
.subcommand(
|
||||
"generate-certificate",
|
||||
from_fn_async(generate_certificate)
|
||||
.with_about("Generate a certificate to use for the webserver")
|
||||
.with_about("about.generate-certificate-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -150,13 +150,13 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Get the certificate for the webserver")
|
||||
.with_about("about.get-certificate-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"enable",
|
||||
from_fn_async(enable_web)
|
||||
.with_about("Enable the webserver")
|
||||
.with_about("about.enable-webserver")
|
||||
.no_display()
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
@@ -164,14 +164,14 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
"disable",
|
||||
from_fn_async(disable_web)
|
||||
.no_display()
|
||||
.with_about("Disable the webserver")
|
||||
.with_about("about.disable-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"reset",
|
||||
from_fn_async(reset_web)
|
||||
.no_display()
|
||||
.with_about("Reset the webserver")
|
||||
.with_about("about.reset-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ impl WgServer {
|
||||
Command::new("wg-quick")
|
||||
.arg("down")
|
||||
.arg(WIREGUARD_INTERFACE_NAME)
|
||||
.env("LANG", "C.UTF-8")
|
||||
.invoke(ErrorKind::Network)
|
||||
.await
|
||||
.or_else(|e| {
|
||||
|
||||
@@ -82,9 +82,7 @@ pub async fn update_system(
|
||||
.de()?
|
||||
{
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Server was already updated. Please restart your device before attempting to update again."
|
||||
),
|
||||
eyre!("{}", t!("update.already-updated-restart-required")),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -143,7 +141,7 @@ pub async fn update_system(
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error returning progress of update: {e}");
|
||||
tracing::error!("{}", t!("update.error-returning-progress", error = e.to_string()));
|
||||
tracing::debug!("{e:?}")
|
||||
}
|
||||
},
|
||||
@@ -176,11 +174,11 @@ pub async fn cli_update_system(
|
||||
.await?,
|
||||
)?;
|
||||
match res.target {
|
||||
None => println!("No updates available"),
|
||||
None => println!("{}", t!("update.no-updates-available")),
|
||||
Some(v) => {
|
||||
if let Some(progress) = res.progress {
|
||||
let mut ws = context.ws_continuation(progress).await?;
|
||||
let mut progress = PhasedProgressBar::new(&format!("Updating to v{v}..."));
|
||||
let mut progress = PhasedProgressBar::new(&t!("update.updating-to-version", version = v.to_string()));
|
||||
let mut prev = None;
|
||||
while let Some(msg) = ws.try_next().await.with_kind(ErrorKind::Network)? {
|
||||
if let tokio_tungstenite::tungstenite::Message::Text(msg) = msg {
|
||||
@@ -201,9 +199,9 @@ pub async fn cli_update_system(
|
||||
prev.overall.set_complete();
|
||||
progress.update(&prev);
|
||||
}
|
||||
println!("Update complete. Restart your server to apply the update.")
|
||||
println!("{}", t!("update.complete-restart-to-apply"))
|
||||
} else {
|
||||
println!("Updating to v{v}...")
|
||||
println!("{}", t!("update.updating-to-version", version = v.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,7 +277,7 @@ async fn maybe_do_update(
|
||||
let mut status = peeked.as_public().as_server_info().as_status_info().de()?;
|
||||
if status.update_progress.is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("Server is already updating!"),
|
||||
eyre!("{}", t!("update.already-updating")),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -296,9 +294,7 @@ async fn maybe_do_update(
|
||||
|
||||
if status.updated {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
"Server was already updated. Please restart your device before attempting to update again."
|
||||
),
|
||||
eyre!("{}", t!("update.already-updated-restart-required")),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
@@ -343,7 +339,7 @@ async fn maybe_do_update(
|
||||
CIRCLE_OF_5THS_SHORT.play().await.log_err();
|
||||
}
|
||||
Err(e) => {
|
||||
let err_string = format!("Update was not successful because of {}", e);
|
||||
let err_string = t!("update.not-successful", error = e.to_string()).to_string();
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_public_mut()
|
||||
@@ -355,7 +351,7 @@ async fn maybe_do_update(
|
||||
db,
|
||||
None,
|
||||
NotificationLevel::Error,
|
||||
"StartOS Update Failed".to_owned(),
|
||||
t!("update.failed-title").to_string(),
|
||||
err_string,
|
||||
(),
|
||||
)
|
||||
|
||||
@@ -67,7 +67,7 @@ pub async fn get_available_governors() -> Result<BTreeSet<Governor>, Error> {
|
||||
for_cpu
|
||||
.entry(current_cpu.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("governors listed before cpu"),
|
||||
eyre!("{}", t!("util.cpupower.governors-listed-before-cpu")),
|
||||
ErrorKind::ParseSysInfo,
|
||||
)
|
||||
})?)
|
||||
@@ -95,6 +95,7 @@ pub async fn current_governor() -> Result<Option<Governor>, Error> {
|
||||
let Some(raw) = Command::new("cpupower")
|
||||
.arg("frequency-info")
|
||||
.arg("-p")
|
||||
.env("LANG", "C.UTF-8")
|
||||
.invoke(ErrorKind::CpuSettings)
|
||||
.await
|
||||
.and_then(|s| Ok(Some(String::from_utf8(s)?)))
|
||||
@@ -122,7 +123,10 @@ pub async fn current_governor() -> Result<Option<Governor>, Error> {
|
||||
}
|
||||
}
|
||||
Err(Error::new(
|
||||
eyre!("Failed to parse cpupower output:\n{raw}"),
|
||||
eyre!(
|
||||
"{}",
|
||||
t!("util.cpupower.failed-to-parse-output", output = raw)
|
||||
),
|
||||
ErrorKind::ParseSysInfo,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -666,6 +666,27 @@ pub fn new_guid() -> InternedString {
|
||||
))
|
||||
}
|
||||
|
||||
/// A utility for lazily computing a Display value. This is useful for i18n
|
||||
/// where you want to defer the translation until the value is actually displayed,
|
||||
/// avoiding allocations in the common case where the message is not rendered.
|
||||
pub struct LazyDisplay<F>(F);
|
||||
impl<F: Fn() -> D, D: fmt::Display> LazyDisplay<F> {
|
||||
pub fn new(f: F) -> Self {
|
||||
LazyDisplay(f)
|
||||
}
|
||||
}
|
||||
impl<F: Fn() -> D, D: fmt::Display> fmt::Display for LazyDisplay<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", (self.0)())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a lazily-evaluated Display implementation.
|
||||
/// The closure is only called when the value is actually displayed.
|
||||
pub fn lazy_display<F: Fn() -> D, D: fmt::Display>(f: F) -> LazyDisplay<F> {
|
||||
LazyDisplay::new(f)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, TS)]
|
||||
#[ts(type = "string")]
|
||||
pub enum PathOrUrl {
|
||||
|
||||
@@ -97,7 +97,7 @@ impl WebSocket {
|
||||
if self.ping_state.is_some() {
|
||||
self.fused = true;
|
||||
break Poll::Ready(Some(Err(axum::Error::new(eyre!(
|
||||
"Timeout: WebSocket did not respond to ping within {PING_TIMEOUT:?}"
|
||||
"{}", t!("util.net.websocket-ping-timeout", timeout = format!("{PING_TIMEOUT:?}"))
|
||||
)))));
|
||||
}
|
||||
self.ping_state = Some((false, rand::random()));
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::util::{Apply, PathOrUrl};
|
||||
pub fn util<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new().subcommand(
|
||||
"b3sum",
|
||||
from_fn_async(b3sum).with_about("Calculate blake3 hash for a file"),
|
||||
from_fn_async(b3sum).with_about("about.calculate-blake3-hash-for-file"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ pub async fn b3sum(
|
||||
.await
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("unknown scheme: {}", url.scheme()),
|
||||
eyre!("{}", t!("util.rpc.unknown-scheme", scheme = url.scheme())),
|
||||
ErrorKind::InvalidRequest,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -652,7 +652,7 @@ impl std::str::FromStr for Duration {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let units_idx = s.find(|c: char| c.is_alphabetic()).ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("Must specify units for duration"),
|
||||
eyre!("{}", t!("util.serde.must-specify-units-for-duration")),
|
||||
crate::ErrorKind::Deserialization,
|
||||
)
|
||||
})?;
|
||||
@@ -691,7 +691,7 @@ impl std::str::FromStr for Duration {
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
eyre!("Invalid units for duration"),
|
||||
eyre!("{}", t!("util.serde.invalid-units-for-duration")),
|
||||
crate::ErrorKind::Deserialization,
|
||||
));
|
||||
}
|
||||
@@ -1050,7 +1050,7 @@ impl<T: TryFrom<Vec<u8>>> FromStr for Base64<T> {
|
||||
.map(Self)
|
||||
.map_err(|_| {
|
||||
Error::new(
|
||||
eyre!("failed to create from buffer"),
|
||||
eyre!("{}", t!("util.serde.failed-to-create-from-buffer")),
|
||||
ErrorKind::Deserialization,
|
||||
)
|
||||
})
|
||||
@@ -1151,7 +1151,7 @@ pub fn apply_expr(input: jaq_core::Val, expr: &str) -> Result<jaq_core::Val, Err
|
||||
|
||||
let Some(expr) = expr else {
|
||||
return Err(Error::new(
|
||||
eyre!("Failed to parse expression: {:?}", errs),
|
||||
eyre!("{}", t!("util.serde.failed-to-parse-expression", errors = format!("{:?}", errs))),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
};
|
||||
@@ -1167,7 +1167,7 @@ pub fn apply_expr(input: jaq_core::Val, expr: &str) -> Result<jaq_core::Val, Err
|
||||
|
||||
if !errs.is_empty() {
|
||||
return Err(Error::new(
|
||||
eyre!("Failed to compile expression: {:?}", errs),
|
||||
eyre!("{}", t!("util.serde.failed-to-compile-expression", errors = format!("{:?}", errs))),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
};
|
||||
@@ -1182,14 +1182,14 @@ pub fn apply_expr(input: jaq_core::Val, expr: &str) -> Result<jaq_core::Val, Err
|
||||
.with_kind(crate::ErrorKind::Deserialization)?
|
||||
else {
|
||||
return Err(Error::new(
|
||||
eyre!("expr returned no results"),
|
||||
eyre!("{}", t!("util.serde.expr-returned-no-results")),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
};
|
||||
|
||||
if res_iter.next().is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("expr returned too many results"),
|
||||
eyre!("{}", t!("util.serde.expr-returned-too-many-results")),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ fn map_miette(m: miette::Error) -> Error {
|
||||
}
|
||||
fn noninteractive_err() -> Error {
|
||||
Error::new(
|
||||
eyre!("Terminal must be in interactive mode for this wizard"),
|
||||
eyre!("{}", t!("util.tui.terminal-must-be-interactive")),
|
||||
ErrorKind::Filesystem,
|
||||
)
|
||||
}
|
||||
@@ -21,7 +21,7 @@ where
|
||||
{
|
||||
move |s| {
|
||||
s.parse::<T>()
|
||||
.map_err(|_| format!("Please enter a valid {what}."))
|
||||
.map_err(|_| t!("util.tui.enter-valid-value", what = what).to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ pub async fn prompt<T, E: std::fmt::Display, Parse: FnMut(&str) -> Result<T, E>>
|
||||
}
|
||||
}
|
||||
ReadlineEvent::Eof | ReadlineEvent::Interrupted => {
|
||||
return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled));
|
||||
return Err(Error::new(eyre!("{}", t!("util.tui.aborted")), ErrorKind::Cancelled));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@@ -83,7 +83,7 @@ pub async fn prompt_multiline<
|
||||
Err(e) => writeln!(&mut rl_ctx.shared_writer, "{e}")?,
|
||||
},
|
||||
ReadlineEvent::Eof | ReadlineEvent::Interrupted => {
|
||||
return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled));
|
||||
return Err(Error::new(eyre!("{}", t!("util.tui.aborted")), ErrorKind::Cancelled));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@@ -119,7 +119,7 @@ pub async fn choose_custom_display<'t, T>(
|
||||
.await
|
||||
.map_err(map_miette)?;
|
||||
if choice.len() < 1 {
|
||||
return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled));
|
||||
return Err(Error::new(eyre!("{}", t!("util.tui.aborted")), ErrorKind::Cancelled));
|
||||
}
|
||||
let (idx, choice_str) = string_choices
|
||||
.iter()
|
||||
@@ -127,7 +127,7 @@ pub async fn choose_custom_display<'t, T>(
|
||||
.find(|(_, s)| s.as_str() == choice[0].as_str())
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("selected choice does not appear in input"),
|
||||
eyre!("{}", t!("util.tui.selected-choice-not-in-input")),
|
||||
ErrorKind::Incoherent,
|
||||
)
|
||||
})?;
|
||||
|
||||
Reference in New Issue
Block a user