0.3.2 final cleanup (#1782)

* bump version with stubbed release notes

* increase BE timeout

* 032 release notes

* hide developer menu for now

* remove unused sub/import

* remoce reconnect from disks res in setup wiz

* remove quirks

* flatten drives response

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
Aiden McClelland
2022-09-08 16:14:42 -06:00
committed by GitHub
parent 5442459b2d
commit b9ce2bf2dc
32 changed files with 154 additions and 395 deletions

View File

@@ -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' }}

2
backend/Cargo.lock generated
View File

@@ -1122,7 +1122,7 @@ dependencies = [
[[package]]
name = "embassy-os"
version = "0.3.1-rev.1"
version = "0.3.2"
dependencies = [
"aes",
"async-stream",

View File

@@ -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"

View File

@@ -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;

View File

@@ -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<PackageId>,
) -> Result<
(
Option<Arc<Revision>>,
BackupMountGuard<TmpMountGuard>,
Vec<JoinHandle<(Result<(), Error>, 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<PackageId>,
backup_guard: &BackupMountGuard<TmpMountGuard>,
) -> Result<
(
Option<Arc<Revision>>,
Vec<(Manifest, PackageBackupMountGuard)>,
),
Error,
> {
) -> Result<Vec<(Manifest, PackageBackupMountGuard)>, 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))]

View File

@@ -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)

View File

@@ -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<Upgraded>,
) -> Result<(), Error> {
loop {

View File

@@ -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<DiskInfo>, 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<IoFormat>,
) -> Result<DiskListResponse, Error> {
) -> Result<Vec<DiskInfo>, Error> {
crate::disk::util::list().await
}

View File

@@ -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<Self, Self::Err> {
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<Self, Self::Err> {
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<Self, Self::Err> {
let s = s.trim();
let mut quirks = BTreeSet::new();
for item in s.split(",") {
if let [vendor, product, "u"] = item.splitn(3, ":").collect::<Vec<_>>().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<Vec<String>, 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<Path>) -> 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<Quirks, Error> {
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::<PathBuf>)
.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(())
}

View File

@@ -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<DiskInfo>,
pub reconnect: Vec<String>,
}
#[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<DiskListResponse, Error> {
let mut quirks = fetch_quirks().await?;
let reconnect = update_quirks(&mut quirks).await?;
save_quirks(&mut quirks).await?;
pub async fn list() -> Result<Vec<DiskInfo>, 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<DiskListResponse, Error> {
})
}
Ok(DiskListResponse {
disks: res,
reconnect,
})
Ok(res)
}
fn parse_pvscan_output(pvscan_output: &str) -> BTreeMap<PathBuf, Option<String>> {

View File

@@ -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);
// }
// }

View File

@@ -94,7 +94,6 @@ impl MdnsControllerInner {
}
self.sync();
}
fn free(&self) {}
}
fn log_str_error(action: &str, e: i32) {

View File

@@ -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<DiskListResponse, Error> {
pub async fn list_disks() -> Result<Vec<DiskInfo>, Error> {
crate::disk::list(None).await
}

View File

@@ -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::Version>),
V0_3_1_1(Wrapper<v0_3_1_1::Version>),
V0_3_1_2(Wrapper<v0_3_1_2::Version>),
V0_3_2(Wrapper<v0_3_2::Version>),
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<Db: DbHandle>(
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),
]
}

View File

@@ -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<Db: DbHandle>(&self, _db: &mut Db) -> Result<(), Error> {

View File

@@ -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<Db: DbHandle>(&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<Db: DbHandle>(&self, _db: &mut Db) -> Result<(), Error> {
Ok(())
}
async fn down<Db: DbHandle>(&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<Db: DbHandle>(&self, _db: &mut Db) -> Result<(), Error> {
Ok(())
}
}

View File

@@ -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<Db: DbHandle>(&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<Db: DbHandle>(&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(())
}
}

View File

@@ -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",

View File

@@ -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": {

View File

@@ -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 = `<ul>${reconnect.map(recon => `<li>${recon}</li>`)}</ul>`
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:<br> ${list}`,
buttons: ['OK'],
})
await alert.present()
}
} catch (e: any) {
this.errorToastService.present(e)
} finally {

View File

@@ -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

View File

@@ -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 = `<ul>${reconnect.map(recon => `<li>${recon}</li>`)}</ul>`
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:<br> ${list}`,
buttons: [
{
role: 'cancel',
text: 'OK',
},
],
})
await alert.present()
}
} catch (e: any) {
this.errToastService.present(e)
} finally {

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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() {

View File

@@ -3,9 +3,8 @@
</a>
<div class="divider"></div>
<ion-item-group class="menu">
<ion-menu-toggle *ngFor="let page of pages; let i = index" auto-hide="false">
<ion-menu-toggle *ngFor="let page of pages" auto-hide="false">
<ion-item
*ngIf="page.url !== '/developer' || (showDevTools$ | async)"
button
class="link"
color="transparent"

View File

@@ -1,5 +1,4 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
import { LocalStorageService } from '../../services/local-storage.service'
import { EOSService } from '../../services/eos.service'
import { PatchDB } from 'patch-db-client'
import { Observable } from 'rxjs'
@@ -37,11 +36,6 @@ export class MenuComponent {
url: '/notifications',
icon: 'notifications-outline',
},
{
title: 'Developer Tools',
url: '/developer',
icon: 'hammer-outline',
},
]
readonly notificationCount$ = this.patch.watch$(
@@ -53,8 +47,6 @@ export class MenuComponent {
readonly showEOSUpdate$ = this.eosService.showUpdate$
readonly showDevTools$ = this.localStorageService.showDevTools$
readonly updateCount$: Observable<number> = this.marketplaceService
.getUpdates()
.pipe(map(pkgs => pkgs.length))
@@ -63,7 +55,6 @@ export class MenuComponent {
constructor(
private readonly patch: PatchDB<DataModel>,
private readonly localStorageService: LocalStorageService,
private readonly eosService: EOSService,
@Inject(AbstractMarketplaceService)
private readonly marketplaceService: MarketplaceService,

View File

@@ -11,11 +11,11 @@
<ion-content class="ion-padding">
<h2>This release</h2>
<h4>0.3.1~1</h4>
<h4>0.3.2</h4>
<p class="note-padding">
View the complete
<a
href="https://github.com/Start9Labs/embassy-os/releases/tag/v0.3.1.1"
href="https://github.com/Start9Labs/embassy-os/releases/tag/v0.3.2"
target="_blank"
noreferrer
>release notes</a
@@ -24,38 +24,12 @@
</p>
<h6>Highlights</h6>
<ul class="spaced-list">
<li>Multiple bug fixes.</li>
</ul>
<br />
<h2>Previous releases in this series</h2>
<h4>0.3.1</h4>
<p class="note-padding">
View the complete
<a
href="https://github.com/Start9Labs/embassy-os/releases/tag/v0.3.1"
target="_blank"
noreferrer
>release notes</a
>
for more details.
</p>
<h6>Highlights</h6>
<ul class="spaced-list">
<li>
Drag and drop installs. Install a service simply by dragging it into the
browser
</li>
<li>
Password reset flow. Requires physical access to the device for security
purposes
</li>
<li>Selective backups. Only back up the services you choose</li>
<li>New button to restart a service</li>
<li>New button to log out all sessions</li>
<li>New button to copy/paste service and OS logs</li>
<li>Significant speedup for service configuration and property viewing</li>
<li>Multiple bugfixes and performance improvements</li>
<li>Autoscrolling for logs</li>
<li>Improved connectivity between browser and Embassy</li>
<li>Switch to Postgres for EOS database for better performance</li>
<li>Multiple bug fixes and under-the-hood improvements</li>
<li>Various UI/UX enhancements</li>
<li>Removal of product keys</li>
</ul>
<div class="ion-text-center ion-padding">
<ion-button

View File

@@ -538,7 +538,7 @@ export class ServerShowPage {
this.clicks++
if (this.clicks >= 5) {
this.clicks = 0
const newVal = await this.localStorageService.toggleShowDiskRepair()
await this.localStorageService.toggleShowDiskRepair()
}
setTimeout(() => {
this.clicks = Math.max(this.clicks - 1, 0)

View File

@@ -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',

View File

@@ -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',

View File

@@ -147,7 +147,6 @@ export interface Manifest extends MarketplaceManifest<DependencyConfig | null> {
backup: BackupActions
migrations: Migrations | null
actions: Record<string, Action>
permissions: any // @TODO 0.3.1
}
export interface DependencyConfig {