diff --git a/iota-cli/src/elements/console_card.rs b/iota-cli/src/elements/console_card.rs index f7b0c8f..a394e96 100644 --- a/iota-cli/src/elements/console_card.rs +++ b/iota-cli/src/elements/console_card.rs @@ -428,7 +428,7 @@ pub async fn run_command(command: &str) { { log!("Created user {}", user.user_id); } else { - log!("Failed to create user"); + log!("User creation: Failed to create user. See errors above."); } } ["user", "remove", username] => { @@ -436,7 +436,7 @@ pub async fn run_command(command: &str) { user_manager::remove_user(user.user_id); log!("Removed user {}", user.user_id); } else { - log!("Failed to find user"); + log!("User removal: Username doesn't exist"); } } ["user", "list"] => { @@ -457,7 +457,7 @@ pub async fn run_command(command: &str) { user_manager::remove_user(user.user_id); log!("Removed user {}", user.user_id); } else { - log!("Failed to find user"); + log!("User info: Username doesn't exist"); } } ["reload"] | ["restart"] => { diff --git a/iota-cli/src/screens/terms_checker.rs b/iota-cli/src/screens/terms_checker.rs index 0d64187..c570769 100644 --- a/iota-cli/src/screens/terms_checker.rs +++ b/iota-cli/src/screens/terms_checker.rs @@ -26,6 +26,7 @@ pub enum UserChoice { AcceptAll, } +#[allow(dead_code)] // ui is unused pub struct TermsCheckerScreen { ui: Arc, sender: Option>, diff --git a/iota-cli/src/ui.rs b/iota-cli/src/ui.rs index 723babe..a44ee74 100644 --- a/iota-cli/src/ui.rs +++ b/iota-cli/src/ui.rs @@ -9,10 +9,7 @@ use ratatui::{Terminal, backend::CrosstermBackend, init}; use std::{ collections::VecDeque, io::Stdout, - sync::{ - Arc, Mutex, - atomic::{AtomicBool, Ordering}, - }, + sync::{Arc, Mutex, atomic::Ordering}, time::Duration, }; use tokio::{sync::RwLock, time::Instant}; diff --git a/iota-core/src/main.rs b/iota-core/src/main.rs index af76140..6ae276a 100644 --- a/iota-core/src/main.rs +++ b/iota-core/src/main.rs @@ -15,7 +15,7 @@ use iota_util::file_util::{download_and_extract_zip, has_dir}; use omikron_connector as omikron; #[tokio::main(flavor = "multi_thread", worker_threads = 16)] -#[allow(unused_must_use, dead_code)] +#[allow(unused_must_use, dead_code, unused_assignments)] async fn main() { while *RELOAD.read().await { *RELOAD.write().await = false; @@ -107,7 +107,9 @@ async fn main() { sb1 = sb1 + ","; } log!("Community IDS: {}", sb1); */ + #[allow(unused_variables)] // port is unused let port = CONFIG.read().await.get_port(); + #[allow(unused_variables)] // ip is unused let mut ip = "0.0.0.0".to_string(); for iface in pnet::datalink::interfaces() { let iface: NetworkInterface = iface; @@ -115,7 +117,7 @@ async fn main() { let ipsv = format!("{}", iface.ips[0]); let ips: &str = ipsv.split('/').next().unwrap_or(""); if format!("{}", ips).starts_with("10.") || format!("{}", ips).starts_with("192.") { - ip = ips.to_string(); + ip = ips.to_string(); // Unused assignments. } } } diff --git a/iota-updater/src/lib.rs b/iota-updater/src/lib.rs index 4d8ddbb..af2982e 100644 --- a/iota-updater/src/lib.rs +++ b/iota-updater/src/lib.rs @@ -7,7 +7,6 @@ use anyhow::{Context, Result, anyhow}; use iota_logger::log; use self_replace::self_replace; use semver::Version; -use std::fs::File; use tempfile::NamedTempFile; const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -108,7 +107,6 @@ async fn download_asset(url: &str) -> Result { } let tmp = NamedTempFile::new().context("failed to create temp file")?; - let mut out = File::create(tmp.path()).context("failed to open temp file")?; let bytes = response .bytes() diff --git a/omikron-connector/src/omikron_connection.rs b/omikron-connector/src/omikron_connection.rs index d6b0ff4..9aa7f15 100755 --- a/omikron-connector/src/omikron_connection.rs +++ b/omikron-connector/src/omikron_connection.rs @@ -79,6 +79,7 @@ impl ConnectionState { // Omikron Connection (Client-side with auto-reconnect) // ============================================================================ +#[allow(dead_code)] // message_send_times is unused. pub struct OmikronConnection { state: Arc>, sender: Arc>>>, @@ -283,6 +284,7 @@ impl OmikronConnection { if iota_id == 0 { log_t!("iota_register_new"); + #[allow(unused_variables)] // priv_k is unused let (pub_k, priv_k) = if let (Some(pk), Some(sk)) = (public_key, private_key) { (pk, sk) } else { @@ -426,9 +428,10 @@ impl OmikronConnection { if cv.is_type(CommunicationType::client_connected) { let user_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0) as i64; + #[allow(unused_variables)] // session_id is unused. let session_id = cv.get_data(DataTypes::session_id).as_number().unwrap_or(0) as i64; - let mut contacts = chats_util::get_users(user_id); + let contacts = chats_util::get_users(user_id); let mut contacts_array = Vec::new(); for (i, contact) in contacts.iter().enumerate() { diff --git a/omikron-connector/src/ping_pong_task.rs b/omikron-connector/src/ping_pong_task.rs index fc21855..18e651f 100644 --- a/omikron-connector/src/ping_pong_task.rs +++ b/omikron-connector/src/ping_pong_task.rs @@ -1,6 +1,5 @@ use crate::omikron_connection::OmikronConnection; use dashmap::DashMap; -use iota_logger::log; use iota_state::APP_STATE; use std::sync::LazyLock; use std::time::Instant; diff --git a/omikron-connector/src/user_ops.rs b/omikron-connector/src/user_ops.rs index 1c34670..eb14bcc 100644 --- a/omikron-connector/src/user_ops.rs +++ b/omikron-connector/src/user_ops.rs @@ -1,6 +1,6 @@ use base64::{Engine as _, engine::general_purpose::STANDARD}; use hex; -use iota_logger::{PrintType, log, log_cv}; +use iota_logger::{PrintType, log, log_cv, log_t}; use iota_state::{RELOAD, SHUTDOWN}; use iota_storage::users::user_manager::{add_user, save_users}; use iota_storage::users::user_profile::UserProfile; @@ -15,27 +15,36 @@ use x448::{PublicKey, Secret}; use crate::omikron_connection::OMIKRON_CONNECTION; pub async fn create_user(username: &str) -> (Option, Option) { - let register_cv = CommunicationValue::new(CommunicationType::get_register); + let register_communication_value = CommunicationValue::new(CommunicationType::get_register); - let conn = OMIKRON_CONNECTION.clone(); + let connection = OMIKRON_CONNECTION.clone(); - let response_cv = match conn - .await_response(®ister_cv, Some(Duration::from_secs(20))) + let response_communication_value = match connection + .await_response(®ister_communication_value, Some(Duration::from_secs(20))) .await { - Ok(cv) => cv, - Err(_) => return (None, None), + Ok(communication_value) => communication_value, + Err(e) => { + log_t!("User creation: {}", e); + return (None, None); + } }; - log_cv!(PrintType::Omega, response_cv); + log_cv!(PrintType::Omega, response_communication_value); - let user_id = match response_cv.get_data(DataTypes::user_id).as_number() { + let user_id = match response_communication_value + .get_data(DataTypes::user_id) + .as_number() + { Some(id) => id, - None => return (None, None), + None => { + log_t!("User creation: Response returned none"); + return (None, None); + } }; - let mut buf = [0u8; 56]; + let mut buffer = [0u8; 56]; let mut rng = OsRng; - rng.fill_bytes(&mut buf); - let private_key = Secret::from_bytes(&buf).unwrap(); + rng.fill_bytes(&mut buffer); + let private_key = Secret::from_bytes(&buffer).unwrap(); let public_key = PublicKey::from(&private_key); let mut hasher = Sha256::new(); @@ -47,7 +56,7 @@ pub async fn create_user(username: &str) -> (Option, Option OsRng.fill_bytes(&mut bytes); let reset_token = STANDARD.encode(&bytes); - let up = UserProfile::new( + let user_profile = UserProfile::new( user_id, username.to_string(), None, @@ -56,7 +65,7 @@ pub async fn create_user(username: &str) -> (Option, Option reset_token.clone(), ); - let cv = CommunicationValue::new(CommunicationType::complete_register_user) + let communication_value = CommunicationValue::new(CommunicationType::complete_register_user) .add_data(DataTypes::user_id, DataValue::Number(user_id)) .add_data(DataTypes::username, DataValue::Str(username.to_string())) .add_data( @@ -66,16 +75,17 @@ pub async fn create_user(username: &str) -> (Option, Option .add_data(DataTypes::iota_id, DataValue::Number(user_id)) .add_data(DataTypes::reset_token, DataValue::Str(reset_token)); - let response_cv = conn - .await_response(&cv, Some(Duration::from_secs(20))) + let response_communication_value = connection + .await_response(&communication_value, Some(Duration::from_secs(20))) .await; - if let Ok(resp) = response_cv { - log_cv!(PrintType::Omega, resp); - if !resp.is_type(CommunicationType::success) { + if let Ok(response) = response_communication_value { + log_cv!(PrintType::Omega, response); + if !response.is_type(CommunicationType::success) { return (None, None); } } else { + log_t!("User creation: Response returned none"); return (None, None); } *SHUTDOWN.write().await = true; @@ -87,7 +97,10 @@ pub async fn create_user(username: &str) -> (Option, Option &format!("{}::{}", user_id, STANDARD.encode(&private_key.as_bytes())), ); - add_user(up.clone()); + add_user(user_profile.clone()); save_users(); - (Some(up), Some(STANDARD.encode(&private_key.as_bytes()))) + ( + Some(user_profile), + Some(STANDARD.encode(&private_key.as_bytes())), + ) } diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..9f676a4 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/util/auto_update.rs b/src/util/auto_update.rs new file mode 100644 index 0000000..090c5a8 --- /dev/null +++ b/src/util/auto_update.rs @@ -0,0 +1,135 @@ +/* This file is used for the auto update function for the Iota. + * It connects to the git server from methanium and checks if + * the version has updated inside the cargo.toml file.*/ + +use anyhow::{Context, Result, anyhow}; +use semver::Version; +use serde::Deserialize; +use std::fs::File; +use std::io::copy; +use tempfile::NamedTempFile; + +use crate::log; // For logging messages into the iota + +const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +const API_BASE: &str = "https://git.methanium.net/api/v1"; +const OWNER: &str = "Tensamin"; +const REPO: &str = "Iota"; + +#[derive(Debug, Deserialize)] +struct Release { + tag_name: String, + assets: Vec, +} + +#[derive(Debug, Deserialize)] +struct Asset { + name: String, + browser_download_url: String, +} + +async fn latest_release() -> Result { + let url = format!("{API_BASE}/repos/{OWNER}/{REPO}/releases/latest"); + + let response = reqwest::get(&url) + .await + .context("failed to query latest release.")?; + + if !response.status().is_success() { + return Err(anyhow!("release API returned {}", response.status())); + } + + Ok(response + .json() + .await + .context("failed to parse release JSON")?) +} + +async fn parse_tag_version(tag: &str) -> Result { + let normalized = tag.strip_prefix('v').unwrap_or(tag); + Ok(Version::parse(normalized)?) +} + +async fn current_version() -> Result { + Ok(Version::parse(CURRENT_VERSION)?) +} + +async fn asset_name_for_current_platform() -> String { + let os = std::env::consts::OS; + let arch = std::env::consts::ARCH; + + match (os, arch) { + ("linux", "x86_64") => "iota-linux-x86_64".to_string(), + ("linux", "aarch64") => "iota-linux-aarch64".to_string(), + ("windows", "x86_64") => "iota-windows-x86_64.exe".to_string(), + ("macos", "x86_64") => "iota-macos-x86_64".to_string(), + ("macos", "aarch64") => "iota-macos-aarch64".to_string(), + _ => panic!("unsupported platform: {os}/{arch}"), + } +} + +async fn download_asset(url: &str) -> Result { + let mut response = reqwest::get(url) + .await + .context("failed to download asset")?; + + if !response.status().is_success() { + return Err(anyhow!("asset download returned {}", response.status())); + } + + let tmp = NamedTempFile::new().context("failed to create temp file")?; + let mut out = File::create(tmp.path()).context("failed to open temp file")?; + + let bytes = response + .bytes() + .await + .context("failed to read response bytes")?; + + std::fs::write(tmp.path(), &bytes).context("failed to write file")?; + + Ok(tmp) +} + +async fn check_for_update() -> Result> { + let current = current_version().await?; + let release = latest_release().await?; + let latest = parse_tag_version(&release.tag_name).await?; + + if latest > current { + Ok(Some(release)) + } else { + Ok(None) + } +} + +async fn perform_update() -> Result { + let Some(release) = check_for_update().await? else { + return Ok(false); + }; + + let wanted_asset = asset_name_for_current_platform().await; + + let asset = release + .assets + .iter() + .find(|a| a.name == wanted_asset) + .ok_or_else(|| anyhow!("no matching asset found: {}", wanted_asset))?; + + log!("Downloading update: {}", asset.name); + + let downloaded = download_asset(&asset.browser_download_url).await?; + + self_replace::self_replace(downloaded.path()) + .context("failed to replace current executable")?; + + Ok(true) +} + +pub async fn check_update() -> Result { + if perform_update().await? { + return Ok(true); + } else { + return Ok(false); + } +} diff --git a/web-ui/src/api.rs b/web-ui/src/api.rs index 7092aba..3c43bf6 100755 --- a/web-ui/src/api.rs +++ b/web-ui/src/api.rs @@ -70,7 +70,7 @@ async fn communities_get(req: HttpRequest, ssl: web::Data) -> impl Respond async fn communities_add( req: HttpRequest, ssl: web::Data, - payload: web::Json, + #[allow(unused_variables)] payload: web::Json, ) -> impl Responder { if !is_allowed_req(&req, *ssl.get_ref()) { return forbidden();