diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index f7c3e3ffe..e87243876 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -75,7 +75,7 @@ jobs: - target: aarch64 snapshot_download: arm_js_snapshot runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 120 needs: build_libs steps: - uses: actions/checkout@v3 @@ -219,7 +219,7 @@ jobs: - name: Run tests run: | ${CARGO_HOME:-~/.cargo}/bin/cargo-nextest nextest run --no-fail-fast --archive-file nextest-archive-${{ matrix.target }}.tar.zst \ - --filter-expr 'not (test(system::test_get_temp) | test(net::tor::test) | test(system::test_get_disk_usage) | test(net::ssl::certificate_details_persist) | test(net::ssl::ca_details_persist) | test(logs::test_logs))' + --filter-expr 'not (test(system::test_get_temp) | test(net::tor::test) | test(system::test_get_disk_usage) | test(net::ssl::certificate_details_persist) | test(net::ssl::ca_details_persist))' if: ${{ matrix.target == 'x86_64' }} - name: Run tests @@ -236,5 +236,5 @@ jobs: mkdir -p ~/.cargo/bin && tar -zxvf nextest-aarch64.tar.gz -C ${CARGO_HOME:-~/.cargo}/bin && ${CARGO_HOME:-~/.cargo}/bin/cargo-nextest nextest run --archive-file nextest-archive-${{ matrix.target }}.tar.zst \ - --filter-expr "not (test(system::test_get_temp) | test(net::tor::test) | test(system::test_get_disk_usage) | test(net::ssl::certificate_details_persist) | test(net::ssl::ca_details_persist) | test(logs::test_logs))"' + --filter-expr "not (test(system::test_get_temp) | test(net::tor::test) | test(system::test_get_disk_usage) | test(net::ssl::certificate_details_persist) | test(net::ssl::ca_details_persist))"' if: ${{ matrix.target == 'aarch64' }} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 3a6a98ea9..265cccc28 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1122,7 +1122,7 @@ dependencies = [ [[package]] name = "embassy-os" -version = "0.3.1-rev.1" +version = "0.3.2" dependencies = [ "aes", "async-stream", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 26bb8d125..fd64d6df3 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -14,7 +14,7 @@ keywords = [ name = "embassy-os" readme = "README.md" repository = "https://github.com/Start9Labs/embassy-os" -version = "0.3.1-rev.1" +version = "0.3.2" [lib] name = "embassy" diff --git a/backend/src/backup/backup_bulk.rs b/backend/src/backup/backup_bulk.rs index cc00c9c72..e3268a271 100644 --- a/backend/src/backup/backup_bulk.rs +++ b/backend/src/backup/backup_bulk.rs @@ -1,6 +1,5 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; -use std::sync::Arc; use chrono::Utc; use clap::ArgMatches; @@ -8,7 +7,7 @@ use color_eyre::eyre::eyre; use helpers::AtomicFile; use openssl::pkey::{PKey, Private}; use openssl::x509::X509; -use patch_db::{DbHandle, LockType, PatchDbHandle, Revision}; +use patch_db::{DbHandle, LockType, PatchDbHandle}; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; use serde_json::Value; diff --git a/backend/src/backup/restore.rs b/backend/src/backup/restore.rs index 02d3bdf15..5c945fe12 100644 --- a/backend/src/backup/restore.rs +++ b/backend/src/backup/restore.rs @@ -9,7 +9,7 @@ use color_eyre::eyre::eyre; use futures::future::BoxFuture; use futures::FutureExt; use openssl::x509::X509; -use patch_db::{DbHandle, PatchDbHandle, Revision}; +use patch_db::{DbHandle, PatchDbHandle}; use rpc_toolkit::command; use tokio::fs::File; use tokio::task::JoinHandle; @@ -57,8 +57,7 @@ pub async fn restore_packages_rpc( let backup_guard = BackupMountGuard::mount(TmpMountGuard::mount(&fs, ReadOnly).await?, &password).await?; - let (revision, backup_guard, tasks, _) = - restore_packages(&ctx, &mut db, backup_guard, ids).await?; + let (backup_guard, tasks, _) = restore_packages(&ctx, &mut db, backup_guard, ids).await?; tokio::spawn(async move { let res = futures::future::join_all(tasks).await; @@ -246,7 +245,7 @@ pub async fn recover_full_embassy( .keys() .cloned() .collect(); - let (_, backup_guard, tasks, progress_info) = restore_packages( + let (backup_guard, tasks, progress_info) = restore_packages( &rpc_ctx, &mut db, backup_guard, @@ -304,14 +303,13 @@ async fn restore_packages( ids: Vec, ) -> Result< ( - Option>, BackupMountGuard, Vec, PackageId)>>, ProgressInfo, ), Error, > { - let (revision, guards) = assure_restoring(ctx, db, ids, &backup_guard).await?; + let guards = assure_restoring(ctx, db, ids, &backup_guard).await?; let mut progress_info = ProgressInfo::default(); @@ -339,7 +337,7 @@ async fn restore_packages( )); } - Ok((revision, backup_guard, tasks, progress_info)) + Ok((backup_guard, tasks, progress_info)) } #[instrument(skip(ctx, db, backup_guard))] @@ -348,13 +346,7 @@ async fn assure_restoring( db: &mut PatchDbHandle, ids: Vec, backup_guard: &BackupMountGuard, -) -> Result< - ( - Option>, - Vec<(Manifest, PackageBackupMountGuard)>, - ), - Error, -> { +) -> Result, Error> { let mut tx = db.begin().await?; let mut guards = Vec::with_capacity(ids.len()); @@ -414,7 +406,8 @@ async fn assure_restoring( guards.push((manifest, guard)); } - Ok((tx.commit().await?, guards)) + tx.commit().await?; + Ok(guards) } #[instrument(skip(ctx, guard))] diff --git a/backend/src/backup/target/mod.rs b/backend/src/backup/target/mod.rs index 6a9c7a9e1..65806ee15 100644 --- a/backend/src/backup/target/mod.rs +++ b/backend/src/backup/target/mod.rs @@ -134,7 +134,6 @@ pub fn target() -> Result<(), Error> { Ok(()) } -// TODO: incorporate reconnect into this response as well #[command(display(display_serializable))] pub async fn list( #[context] ctx: RpcContext, @@ -143,7 +142,6 @@ pub async fn list( let (disks_res, cifs) = tokio::try_join!(crate::disk::util::list(), cifs::list(&mut sql_handle),)?; Ok(disks_res - .disks .into_iter() .flat_map(|mut disk| { std::mem::take(&mut disk.partitions) diff --git a/backend/src/db/mod.rs b/backend/src/db/mod.rs index c7f7aa725..1f0ce0fdd 100644 --- a/backend/src/db/mod.rs +++ b/backend/src/db/mod.rs @@ -77,7 +77,7 @@ async fn subscribe_to_session_kill( async fn deal_with_messages( _has_valid_authentication: HasValidSession, mut kill: oneshot::Receiver<()>, - mut sub: patch_db::Subscriber, + sub: patch_db::Subscriber, mut stream: WebSocketStream, ) -> Result<(), Error> { loop { diff --git a/backend/src/disk/mod.rs b/backend/src/disk/mod.rs index 8ba88424d..4cc2b5ce9 100644 --- a/backend/src/disk/mod.rs +++ b/backend/src/disk/mod.rs @@ -1,7 +1,7 @@ use clap::ArgMatches; use rpc_toolkit::command; -use self::util::DiskListResponse; +use crate::disk::util::DiskInfo; use crate::util::display_none; use crate::util::serde::{display_serializable, IoFormat}; use crate::Error; @@ -9,7 +9,6 @@ use crate::Error; pub mod fsck; pub mod main; pub mod mount; -pub mod quirks; pub mod util; pub const BOOT_RW_PATH: &str = "/media/boot-rw"; @@ -20,7 +19,7 @@ pub fn disk() -> Result<(), Error> { Ok(()) } -fn display_disk_info(info: DiskListResponse, matches: &ArgMatches) { +fn display_disk_info(info: Vec, matches: &ArgMatches) { use prettytable::*; if matches.is_present("format") { @@ -35,7 +34,7 @@ fn display_disk_info(info: DiskListResponse, matches: &ArgMatches) { "USED", "EMBASSY OS VERSION" ]); - for disk in info.disks { + for disk in info { let row = row![ disk.logicalname.display(), "N/A", @@ -79,7 +78,7 @@ pub async fn list( #[allow(unused_variables)] #[arg] format: Option, -) -> Result { +) -> Result, Error> { crate::disk::util::list().await } diff --git a/backend/src/disk/quirks.rs b/backend/src/disk/quirks.rs deleted file mode 100644 index 8fb2f8fea..000000000 --- a/backend/src/disk/quirks.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::collections::BTreeSet; -use std::num::ParseIntError; -use std::path::{Path, PathBuf}; - -use color_eyre::eyre::eyre; -use helpers::AtomicFile; -use tokio::io::AsyncWriteExt; -use tracing::instrument; - -use super::BOOT_RW_PATH; -use crate::{Error, ErrorKind, ResultExt}; - -pub const QUIRK_PATH: &'static str = "/sys/module/usb_storage/parameters/quirks"; - -pub const WHITELIST: [(VendorId, ProductId); 5] = [ - (VendorId(0x1d6b), ProductId(0x0002)), // root hub usb2 - (VendorId(0x1d6b), ProductId(0x0003)), // root hub usb3 - (VendorId(0x2109), ProductId(0x3431)), - (VendorId(0x1058), ProductId(0x262f)), // western digital black HDD - (VendorId(0x04e8), ProductId(0x4001)), // Samsung T7 -]; - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] -pub struct VendorId(u16); -impl std::str::FromStr for VendorId { - type Err = ParseIntError; - fn from_str(s: &str) -> Result { - u16::from_str_radix(s.trim(), 16).map(VendorId) - } -} -impl std::fmt::Display for VendorId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:04x}", self.0) - } -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] -pub struct ProductId(u16); -impl std::str::FromStr for ProductId { - type Err = ParseIntError; - fn from_str(s: &str) -> Result { - u16::from_str_radix(s.trim(), 16).map(ProductId) - } -} -impl std::fmt::Display for ProductId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:04x}", self.0) - } -} - -#[derive(Clone, Debug)] -pub struct Quirks(BTreeSet<(VendorId, ProductId)>); -impl Quirks { - pub fn add(&mut self, vendor: VendorId, product: ProductId) { - self.0.insert((vendor, product)); - } - pub fn remove(&mut self, vendor: VendorId, product: ProductId) { - self.0.remove(&(vendor, product)); - } - pub fn contains(&self, vendor: VendorId, product: ProductId) -> bool { - self.0.contains(&(vendor, product)) - } -} -impl std::fmt::Display for Quirks { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut comma = false; - for (vendor, product) in &self.0 { - if comma { - write!(f, ",")?; - } else { - comma = true; - } - write!(f, "{}:{}:u", vendor, product)?; - } - Ok(()) - } -} -impl std::str::FromStr for Quirks { - type Err = Error; - fn from_str(s: &str) -> Result { - let s = s.trim(); - let mut quirks = BTreeSet::new(); - for item in s.split(",") { - if let [vendor, product, "u"] = item.splitn(3, ":").collect::>().as_slice() { - quirks.insert((vendor.parse()?, product.parse()?)); - } else { - return Err(Error::new( - eyre!("Invalid quirk: `{}`", item), - crate::ErrorKind::DiskManagement, - )); - } - } - Ok(Quirks(quirks)) - } -} - -#[instrument] -pub async fn update_quirks(quirks: &mut Quirks) -> Result, Error> { - let mut usb_devices = tokio::fs::read_dir("/sys/bus/usb/devices/").await?; - let mut to_reconnect = Vec::new(); - while let Some(usb_device) = usb_devices.next_entry().await? { - if tokio::fs::metadata(usb_device.path().join("idVendor")) - .await - .is_err() - { - continue; - } - let vendor = tokio::fs::read_to_string(usb_device.path().join("idVendor")) - .await? - .parse()?; - let product = tokio::fs::read_to_string(usb_device.path().join("idProduct")) - .await? - .parse()?; - if WHITELIST.contains(&(vendor, product)) { - quirks.remove(vendor, product); - continue; - } - if quirks.contains(vendor, product) { - continue; - } - quirks.add(vendor, product); - { - // write quirks to sysfs - let mut quirk_file = tokio::fs::File::create(QUIRK_PATH).await?; - quirk_file.write_all(quirks.to_string().as_bytes()).await?; - quirk_file.sync_all().await?; - drop(quirk_file); - } - - disconnect_usb(usb_device.path()).await?; - let (vendor_name, product_name) = tokio::try_join!( - tokio::fs::read_to_string(usb_device.path().join("manufacturer")), - tokio::fs::read_to_string(usb_device.path().join("product")), - )?; - to_reconnect.push(format!("{} {}", vendor_name, product_name)); - } - Ok(to_reconnect) -} - -#[instrument(skip(usb_device_path))] -pub async fn disconnect_usb(usb_device_path: impl AsRef) -> Result<(), Error> { - let authorized_path = usb_device_path.as_ref().join("bConfigurationValue"); - let mut authorized_file = tokio::fs::File::create(&authorized_path).await?; - authorized_file.write_all(b"0").await?; - authorized_file.sync_all().await?; - drop(authorized_file); - Ok(()) -} - -#[instrument] -pub async fn fetch_quirks() -> Result { - Ok(tokio::fs::read_to_string(QUIRK_PATH).await?.parse()?) -} - -#[instrument] -pub async fn save_quirks(quirks: &Quirks) -> Result<(), Error> { - let orig_path = Path::new(BOOT_RW_PATH).join("cmdline.txt.orig"); - let target_path = Path::new(BOOT_RW_PATH).join("cmdline.txt"); - if tokio::fs::metadata(&orig_path).await.is_err() { - tokio::fs::copy(&target_path, &orig_path).await?; - } - let cmdline = tokio::fs::read_to_string(&orig_path).await?; - let mut target = AtomicFile::new(&target_path, None::) - .await - .with_kind(ErrorKind::Filesystem)?; - target - .write_all(format!("usb-storage.quirks={} {}", quirks, cmdline).as_bytes()) - .await?; - target.save().await.with_kind(ErrorKind::Filesystem)?; - - Ok(()) -} diff --git a/backend/src/disk/util.rs b/backend/src/disk/util.rs index 82e56e107..a082da21a 100644 --- a/backend/src/disk/util.rs +++ b/backend/src/disk/util.rs @@ -19,19 +19,11 @@ use tracing::instrument; use super::mount::filesystem::block_dev::BlockDev; use super::mount::filesystem::ReadOnly; use super::mount::guard::TmpMountGuard; -use super::quirks::{fetch_quirks, save_quirks, update_quirks}; use crate::util::io::from_yaml_async_reader; use crate::util::serde::IoFormat; use crate::util::{Invoke, Version}; use crate::{Error, ResultExt as _}; -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct DiskListResponse { - pub disks: Vec, - pub reconnect: Vec, -} - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct DiskInfo { @@ -240,10 +232,7 @@ pub async fn recovery_info( } #[instrument] -pub async fn list() -> Result { - let mut quirks = fetch_quirks().await?; - let reconnect = update_quirks(&mut quirks).await?; - save_quirks(&mut quirks).await?; +pub async fn list() -> Result, Error> { let disk_guids = pvscan().await?; let disks = tokio_stream::wrappers::ReadDirStream::new( tokio::fs::read_dir(DISK_PATH) @@ -374,10 +363,7 @@ pub async fn list() -> Result { }) } - Ok(DiskListResponse { - disks: res, - reconnect, - }) + Ok(res) } fn parse_pvscan_output(pvscan_output: &str) -> BTreeMap> { diff --git a/backend/src/logs.rs b/backend/src/logs.rs index 6f654b196..1e17bbfd2 100644 --- a/backend/src/logs.rs +++ b/backend/src/logs.rs @@ -508,26 +508,26 @@ pub async fn follow_logs( // println!("{}", serialized); // } -#[tokio::test] -pub async fn test_logs() { - let mut cmd = Command::new("journalctl"); - cmd.kill_on_drop(true); +// #[tokio::test] +// pub async fn test_logs() { +// let mut cmd = Command::new("journalctl"); +// cmd.kill_on_drop(true); - cmd.arg("-f"); - cmd.arg("CONTAINER_NAME=hello-world.embassy"); +// cmd.arg("-f"); +// cmd.arg("CONTAINER_NAME=hello-world.embassy"); - let mut child = cmd.stdout(Stdio::piped()).spawn().unwrap(); - let out = BufReader::new( - child - .stdout - .take() - .ok_or_else(|| Error::new(eyre!("No stdout available"), crate::ErrorKind::Journald)) - .unwrap(), - ); +// let mut child = cmd.stdout(Stdio::piped()).spawn().unwrap(); +// let out = BufReader::new( +// child +// .stdout +// .take() +// .ok_or_else(|| Error::new(eyre!("No stdout available"), crate::ErrorKind::Journald)) +// .unwrap(), +// ); - let mut journalctl_entries = LinesStream::new(out.lines()); +// let mut journalctl_entries = LinesStream::new(out.lines()); - while let Some(line) = journalctl_entries.try_next().await.unwrap() { - dbg!(line); - } -} +// while let Some(line) = journalctl_entries.try_next().await.unwrap() { +// dbg!(line); +// } +// } diff --git a/backend/src/net/mdns.rs b/backend/src/net/mdns.rs index beea99cad..33b67eede 100644 --- a/backend/src/net/mdns.rs +++ b/backend/src/net/mdns.rs @@ -94,7 +94,6 @@ impl MdnsControllerInner { } self.sync(); } - fn free(&self) {} } fn log_str_error(action: &str, e: i32) { diff --git a/backend/src/setup.rs b/backend/src/setup.rs index 3e654e35a..47c30c6c9 100644 --- a/backend/src/setup.rs +++ b/backend/src/setup.rs @@ -36,7 +36,7 @@ use crate::disk::mount::filesystem::block_dev::BlockDev; use crate::disk::mount::filesystem::cifs::Cifs; use crate::disk::mount::filesystem::ReadOnly; use crate::disk::mount::guard::TmpMountGuard; -use crate::disk::util::{pvscan, recovery_info, DiskListResponse, EmbassyOsRecoveryInfo}; +use crate::disk::util::{pvscan, recovery_info, DiskInfo, EmbassyOsRecoveryInfo}; use crate::disk::REPAIR_DISK_PATH; use crate::hostname::{get_hostname, Hostname}; use crate::id::Id; @@ -87,7 +87,7 @@ pub fn disk() -> Result<(), Error> { } #[command(rename = "list", rpc_only, metadata(authenticated = false))] -pub async fn list_disks() -> Result { +pub async fn list_disks() -> Result, Error> { crate::disk::list(None).await } diff --git a/backend/src/version/mod.rs b/backend/src/version/mod.rs index afe94eacb..7c754aa0b 100644 --- a/backend/src/version/mod.rs +++ b/backend/src/version/mod.rs @@ -15,8 +15,9 @@ mod v0_3_0_3; mod v0_3_1; mod v0_3_1_1; mod v0_3_1_2; +mod v0_3_2; -pub type Current = v0_3_1_2::Version; +pub type Current = v0_3_2::Version; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[serde(untagged)] @@ -28,6 +29,7 @@ enum Version { V0_3_1(Wrapper), V0_3_1_1(Wrapper), V0_3_1_2(Wrapper), + V0_3_2(Wrapper), Other(emver::Version), } @@ -50,6 +52,7 @@ impl Version { Version::V0_3_1(Wrapper(x)) => x.semver(), Version::V0_3_1_1(Wrapper(x)) => x.semver(), Version::V0_3_1_2(Wrapper(x)) => x.semver(), + Version::V0_3_2(Wrapper(x)) => x.semver(), Version::Other(x) => x.clone(), } } @@ -183,6 +186,7 @@ pub async fn init( Version::V0_3_1(v) => v.0.migrate_to(&Current::new(), db, receipts).await?, Version::V0_3_1_1(v) => v.0.migrate_to(&Current::new(), db, receipts).await?, Version::V0_3_1_2(v) => v.0.migrate_to(&Current::new(), db, receipts).await?, + Version::V0_3_2(v) => v.0.migrate_to(&Current::new(), db, receipts).await?, Version::Other(_) => { return Err(Error::new( eyre!("Cannot downgrade"), @@ -221,6 +225,8 @@ mod tests { Just(Version::V0_3_0_3(Wrapper(v0_3_0_3::Version::new()))), Just(Version::V0_3_1(Wrapper(v0_3_1::Version::new()))), Just(Version::V0_3_1_1(Wrapper(v0_3_1_1::Version::new()))), + Just(Version::V0_3_1_2(Wrapper(v0_3_1_2::Version::new()))), + Just(Version::V0_3_2(Wrapper(v0_3_2::Version::new()))), em_version().prop_map(Version::Other), ] } diff --git a/backend/src/version/v0_3_0_1.rs b/backend/src/version/v0_3_0_1.rs index b6fe14bb3..577eb9f66 100644 --- a/backend/src/version/v0_3_0_1.rs +++ b/backend/src/version/v0_3_0_1.rs @@ -4,7 +4,6 @@ use emver::VersionRange; use tokio::process::Command; use super::*; -use crate::disk::quirks::{fetch_quirks, save_quirks, update_quirks}; use crate::disk::BOOT_RW_PATH; use crate::update::query_mounted_label; use crate::util::Invoke; @@ -36,9 +35,6 @@ impl VersionT for Version { .arg(Path::new(BOOT_RW_PATH).join("cmdline.txt.orig")) .invoke(crate::ErrorKind::Filesystem) .await?; - let mut q = fetch_quirks().await?; - update_quirks(&mut q).await?; - save_quirks(&q).await?; Ok(()) } async fn down(&self, _db: &mut Db) -> Result<(), Error> { diff --git a/backend/src/version/v0_3_1_2.rs b/backend/src/version/v0_3_1_2.rs index 9bf66efe0..a3a672e04 100644 --- a/backend/src/version/v0_3_1_2.rs +++ b/backend/src/version/v0_3_1_2.rs @@ -1,7 +1,5 @@ use emver::VersionRange; -use crate::hostname::{generate_id, get_hostname, sync_hostname}; - use super::v0_3_0::V0_3_0_COMPAT; use super::*; @@ -21,41 +19,10 @@ impl VersionT for Version { fn compat(&self) -> &'static VersionRange { &*V0_3_0_COMPAT } - async fn up(&self, db: &mut Db) -> Result<(), Error> { - let hostname = get_hostname(db).await?; - crate::db::DatabaseModel::new() - .server_info() - .hostname() - .put(db, &Some(hostname.0)) - .await?; - crate::db::DatabaseModel::new() - .server_info() - .id() - .put(db, &generate_id()) - .await?; - - sync_hostname(db).await?; - let mut ui = crate::db::DatabaseModel::new() - .ui() - .get(db, false) - .await? - .clone(); - if let serde_json::Value::Object(ref mut ui) = ui { - ui.insert("ack-instructions".to_string(), serde_json::json!({})); - } - crate::db::DatabaseModel::new().ui().put(db, &ui).await?; + async fn up(&self, _db: &mut Db) -> Result<(), Error> { Ok(()) } - async fn down(&self, db: &mut Db) -> Result<(), Error> { - let mut ui = crate::db::DatabaseModel::new() - .ui() - .get(db, false) - .await? - .clone(); - if let serde_json::Value::Object(ref mut ui) = ui { - ui.remove("ack-instructions"); - } - crate::db::DatabaseModel::new().ui().put(db, &ui).await?; + async fn down(&self, _db: &mut Db) -> Result<(), Error> { Ok(()) } } diff --git a/backend/src/version/v0_3_2.rs b/backend/src/version/v0_3_2.rs new file mode 100644 index 000000000..cc2b227c4 --- /dev/null +++ b/backend/src/version/v0_3_2.rs @@ -0,0 +1,61 @@ +use emver::VersionRange; + +use crate::hostname::{generate_id, get_hostname, sync_hostname}; + +use super::v0_3_0::V0_3_0_COMPAT; +use super::*; + +const V0_3_2: emver::Version = emver::Version::new(0, 3, 2, 0); + +#[derive(Clone, Debug)] +pub struct Version; +#[async_trait] +impl VersionT for Version { + type Previous = v0_3_1_2::Version; + fn new() -> Self { + Version + } + fn semver(&self) -> emver::Version { + V0_3_2 + } + fn compat(&self) -> &'static VersionRange { + &*V0_3_0_COMPAT + } + async fn up(&self, db: &mut Db) -> Result<(), Error> { + let hostname = get_hostname(db).await?; + crate::db::DatabaseModel::new() + .server_info() + .hostname() + .put(db, &Some(hostname.0)) + .await?; + crate::db::DatabaseModel::new() + .server_info() + .id() + .put(db, &generate_id()) + .await?; + + sync_hostname(db).await?; + let mut ui = crate::db::DatabaseModel::new() + .ui() + .get(db, false) + .await? + .clone(); + if let serde_json::Value::Object(ref mut ui) = ui { + ui.insert("ack-instructions".to_string(), serde_json::json!({})); + } + crate::db::DatabaseModel::new().ui().put(db, &ui).await?; + Ok(()) + } + async fn down(&self, db: &mut Db) -> Result<(), Error> { + let mut ui = crate::db::DatabaseModel::new() + .ui() + .get(db, false) + .await? + .clone(); + if let serde_json::Value::Object(ref mut ui) = ui { + ui.remove("ack-instructions"); + } + crate::db::DatabaseModel::new().ui().put(db, &ui).await?; + Ok(()) + } +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d7876917f..75dcf4fd6 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "embassy-os", - "version": "0.3.1.1", + "version": "0.3.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "embassy-os", - "version": "0.3.1.1", + "version": "0.3.2", "dependencies": { "@angular/animations": "^14.1.0", "@angular/common": "^14.1.0", diff --git a/frontend/package.json b/frontend/package.json index 5b6304df5..a3b92fb03 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "embassy-os", - "version": "0.3.1.1", + "version": "0.3.2", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "scripts": { diff --git a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts index 727cd602b..76b552513 100644 --- a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts @@ -49,7 +49,7 @@ export class EmbassyPage { async getDrives() { this.loading = true try { - const { disks, reconnect } = await this.apiService.getDrives() + const disks = await this.apiService.getDrives() this.storageDrives = disks.filter( d => !d.partitions @@ -59,15 +59,6 @@ export class EmbassyPage { ?.logicalname, ), ) - if (!this.storageDrives.length && reconnect.length) { - const list = `
    ${reconnect.map(recon => `
  • ${recon}
  • `)}
` - const alert = await this.alertCtrl.create({ - header: 'Warning', - message: `One or more devices you connected had to be reconfigured to support the current hardware platform. Please unplug and replug the following device(s), then refresh the page:
${list}`, - buttons: ['OK'], - }) - await alert.present() - } } catch (e: any) { this.errorToastService.present(e) } finally { diff --git a/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts b/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts index 17514b4a4..925bc3cc0 100644 --- a/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts @@ -39,7 +39,7 @@ export class HomePage { async ngOnInit() { try { this.encrypted.secret = await this.unencrypted.getSecret() - const { disks } = await this.unencrypted.getDrives() + const disks = await this.unencrypted.getDrives() this.guid = disks.find(d => !!d.guid)?.guid } catch (e: any) { this.error = true diff --git a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts index 5f077bfd9..b0ef6273c 100644 --- a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts @@ -1,5 +1,5 @@ import { Component, Input } from '@angular/core' -import { AlertController, ModalController, NavController } from '@ionic/angular' +import { ModalController, NavController } from '@ionic/angular' import { CifsModal } from 'src/app/modals/cifs-modal/cifs-modal.page' import { ApiService, DiskBackupTarget } from 'src/app/services/api/api.service' import { ErrorToastService } from '@start9labs/shared' @@ -20,7 +20,6 @@ export class RecoverPage { private readonly navCtrl: NavController, private readonly modalCtrl: ModalController, private readonly modalController: ModalController, - private readonly alertCtrl: AlertController, private readonly errToastService: ErrorToastService, private readonly stateService: StateService, ) {} @@ -41,7 +40,7 @@ export class RecoverPage { async getDrives() { this.mappedDrives = [] try { - const { disks, reconnect } = await this.apiService.getDrives() + const disks = await this.apiService.getDrives() disks .filter(d => d.partitions.length) .forEach(d => { @@ -62,21 +61,6 @@ export class RecoverPage { }) }) }) - - if (!this.mappedDrives.length && reconnect.length) { - const list = `
    ${reconnect.map(recon => `
  • ${recon}
  • `)}
` - const alert = await this.alertCtrl.create({ - header: 'Warning', - message: `One or more devices you connected had to be reconfigured to support the current hardware platform. Please unplug and replug the following device(s), then refresh the page:
${list}`, - buttons: [ - { - role: 'cancel', - text: 'OK', - }, - ], - }) - await alert.present() - } } catch (e: any) { this.errToastService.present(e) } finally { diff --git a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts index 31b110a44..7a897566b 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts @@ -42,10 +42,7 @@ export type EmbassyOSRecoveryInfo = { 'wrapped-key': string | null } -export type DiskListResponse = { - disks: DiskInfo[] - reconnect: string[] -} +export type DiskListResponse = DiskInfo[] export type DiskBackupTarget = { vendor: string | null diff --git a/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts index 6f4c3197d..69cb23aaa 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts @@ -41,7 +41,7 @@ export class LiveApiService implements ApiService { /** * We want to update the secret, which means that we will call in clearnet the * getSecret, and all the information is never in the clear, and only public - * information is sent across the network. We don't want to expose that we do + * information is sent across the network. We don't want to expose that we do * this wil all public/private key, which means that there is no information loss * through the network. */ diff --git a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts index 25485fcf0..c230ee5b9 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts @@ -37,32 +37,29 @@ export class MockApiService implements ApiService { async getDrives() { await pauseFor(1000) - return { - disks: [ - { - logicalname: 'abcd', - vendor: 'Samsung', - model: 'T5', - partitions: [ - { - logicalname: 'pabcd', - label: null, - capacity: 73264762332, - used: null, - 'embassy-os': { - version: '0.2.17', - full: true, - 'password-hash': null, - 'wrapped-key': null, - }, + return [ + { + logicalname: 'abcd', + vendor: 'Samsung', + model: 'T5', + partitions: [ + { + logicalname: 'pabcd', + label: null, + capacity: 73264762332, + used: null, + 'embassy-os': { + version: '0.2.17', + full: true, + 'password-hash': null, + 'wrapped-key': null, }, - ], - capacity: 123456789123, - guid: 'uuid-uuid-uuid-uuid', - }, - ], - reconnect: [], - } + }, + ], + capacity: 123456789123, + guid: 'uuid-uuid-uuid-uuid', + }, + ] } async set02XDrive() { diff --git a/frontend/projects/ui/src/app/app/menu/menu.component.html b/frontend/projects/ui/src/app/app/menu/menu.component.html index c7dc61935..7e3ca3ead 100644 --- a/frontend/projects/ui/src/app/app/menu/menu.component.html +++ b/frontend/projects/ui/src/app/app/menu/menu.component.html @@ -3,9 +3,8 @@
- + = this.marketplaceService .getUpdates() .pipe(map(pkgs => pkgs.length)) @@ -63,7 +55,6 @@ export class MenuComponent { constructor( private readonly patch: PatchDB, - private readonly localStorageService: LocalStorageService, private readonly eosService: EOSService, @Inject(AbstractMarketplaceService) private readonly marketplaceService: MarketplaceService, diff --git a/frontend/projects/ui/src/app/modals/os-welcome/os-welcome.page.html b/frontend/projects/ui/src/app/modals/os-welcome/os-welcome.page.html index bbe098cb8..563153fcf 100644 --- a/frontend/projects/ui/src/app/modals/os-welcome/os-welcome.page.html +++ b/frontend/projects/ui/src/app/modals/os-welcome/os-welcome.page.html @@ -11,11 +11,11 @@

This release

-

0.3.1~1

+

0.3.2

View the complete release notes

Highlights
    -
  • Multiple bug fixes.
  • -
- -
-

Previous releases in this series

-

0.3.1

-

- View the complete - release notes - for more details. -

-
Highlights
-
    -
  • - Drag and drop installs. Install a service simply by dragging it into the - browser -
  • -
  • - Password reset flow. Requires physical access to the device for security - purposes -
  • -
  • Selective backups. Only back up the services you choose
  • -
  • New button to restart a service
  • -
  • New button to log out all sessions
  • -
  • New button to copy/paste service and OS logs
  • -
  • Significant speedup for service configuration and property viewing
  • -
  • Multiple bugfixes and performance improvements
  • +
  • Autoscrolling for logs
  • +
  • Improved connectivity between browser and Embassy
  • +
  • Switch to Postgres for EOS database for better performance
  • +
  • Multiple bug fixes and under-the-hood improvements
  • +
  • Various UI/UX enhancements
  • +
  • Removal of product keys
= 5) { this.clicks = 0 - const newVal = await this.localStorageService.toggleShowDiskRepair() + await this.localStorageService.toggleShowDiskRepair() } setTimeout(() => { this.clicks = Math.max(this.clicks - 1, 0) diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index d1b8d8e54..ae79971e3 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -338,7 +338,6 @@ export module Mock { }, }, }, - permissions: {}, dependencies: {}, } @@ -472,7 +471,6 @@ export module Mock { 'input-spec': null, }, }, - permissions: {}, dependencies: { bitcoind: { version: '=0.21.0', @@ -587,7 +585,6 @@ export module Mock { }, migrations: null, actions: {}, - permissions: {}, dependencies: { bitcoind: { version: '>=0.20.0', diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index 8fe87c35f..7e549fd77 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -27,7 +27,7 @@ export const mockPatchData: DataModel = { }, 'server-info': { id: 'abcdefgh', - version: '0.3.1.1', + version: '0.3.2', 'last-backup': new Date(new Date().valueOf() - 604800001).toISOString(), 'lan-address': 'https://embassy-abcdefgh.local', 'tor-address': 'http://myveryownspecialtoraddress.onion', @@ -381,7 +381,6 @@ export const mockPatchData: DataModel = { }, }, }, - permissions: {}, dependencies: {}, }, installed: { @@ -578,7 +577,6 @@ export const mockPatchData: DataModel = { 'input-spec': null, }, }, - permissions: {}, dependencies: { bitcoind: { version: '=0.21.0', diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index ffff20bfd..f1a8e797e 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -147,7 +147,6 @@ export interface Manifest extends MarketplaceManifest { backup: BackupActions migrations: Migrations | null actions: Record - permissions: any // @TODO 0.3.1 } export interface DependencyConfig {