Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rust for web v1 #9464

Draft
wants to merge 7 commits into
base: ms-weeb-testbed-login
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 182 additions & 35 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ glob = { version = "0.3.2", default-features = false }
gloo-timers = { version = "0.3.0", default-features = false }
hex = { version = "0.4.3", default-features = false }
hex-literal = { version = "0.4.1", default-features = false }
indexed_db_futures = { version = "0.5.0", default-features = false }
indexed-db = { version = "0.4.2", default-features = false }
indexed_db_futures = { version = "0.6.0", default-features = false, path = "../rust-indexed-db" }
itertools = { version = "0.12.1", default-features = false }
jni = { version = "0.21.1", default-features = false }
js-sys = { version = "0.3.70", default-features = false }
Expand Down
8 changes: 7 additions & 1 deletion bindings/web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@ pub fn initLogger() {
{
console_error_panic_hook::set_once();
}
console_log::init_with_level(log::Level::Info).expect("cannot initialize console logger");
let log_level = if cfg!(debug_assertions) {
log::Level::Trace
} else {
log::Level::Info
};
console_log::init_with_level(log_level).expect("cannot initialize console logger");
log::info!("Libparsec logger initialized with level {log_level}");
}
3 changes: 3 additions & 0 deletions libparsec/crates/client/src/certif/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub(super) async fn add_certificates_batch(
return Ok(MaybeRedactedSwitch::NoSwitch);
}

log::debug!("Add certificates batch: as work to do");
let send_event_on_invalid_certificate = |err: CertifAddCertificatesBatchError| {
if let CertifAddCertificatesBatchError::InvalidCertificate(what) = err {
let event = EventInvalidCertificate(what);
Expand All @@ -191,8 +192,10 @@ pub(super) async fn add_certificates_batch(
};

let initial_stored_last_timestamps = store.get_last_timestamps().await?;
log::debug!("Add certificates batch: last_timestamp={initial_stored_last_timestamps:?}");
let storage_initially_empty = initial_stored_last_timestamps.is_empty();
let initial_self_profile = store.get_current_self_profile().await?;
log::debug!("Add certificates batch: self_profile={initial_self_profile}");

// If a certificate is invalid we exit without any further validation: the
// write operation is going to be rolled back.
Expand Down
11 changes: 8 additions & 3 deletions libparsec/crates/client/src/certif/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@
// be rollback on drop.
match write_guard.storage.commit().await {
Err(commit_err) => {
log::error!(
"Failed to commit transaction for certificate storage: {commit_err}"
);
reset_cache();
Err(commit_err.into())
}
Expand All @@ -265,6 +268,7 @@
}
}
} else {
log::debug!("Operation failed for certificate storage, not commiting transaction");

Check warning on line 271 in libparsec/crates/client/src/certif/store.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Misspelled word (commiting) Suggestions: (committing*)
reset_cache();
// Ok(Err(...))
Ok(outcome)
Expand All @@ -291,7 +295,7 @@
Some(storage) => storage,
};

let mut write_guard = CertificatesStoreReadGuard {
let mut read_guard = CertificatesStoreReadGuard {
store: self,
storage,
};
Expand All @@ -305,9 +309,9 @@
// of a Future returned by a closure depends on the closure parameter if
// they are references (see `for_write` code).
// TODO: Remove this once async closure are available
let static_write_guard_mut_ref = unsafe { pretend_static(&mut write_guard) };
let static_read_guard_mut_ref = unsafe { pretend_static(&mut read_guard) };

let fut = cb(static_write_guard_mut_ref);
let fut = cb(static_read_guard_mut_ref);
let outcome = fut.await;

Ok(outcome)
Expand Down Expand Up @@ -469,6 +473,7 @@
.lock()
.expect("Mutex is poisoned !");
if let ScalarCache::Present(last_timestamps) = &guard.per_topic_last_timestamps {
log::trace!("Cached last_timestamps");
return Ok(last_timestamps.to_owned());
}
}
Expand Down
4 changes: 3 additions & 1 deletion libparsec/crates/platform_device_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ pub async fn load_device(
) -> Result<Arc<LocalDevice>, LoadDeviceError> {
#[cfg(feature = "test-with-testbed")]
if let Some(result) = testbed::maybe_load_device(config_dir, access) {
return result;
return result.inspect_err(|e| log::error!("Failed to load device from testbed: {e}"));
} else {
log::trace!("Device not found in testbed");
}

platform::load_device(access)
Expand Down
4 changes: 4 additions & 0 deletions libparsec/crates/platform_device_loader/src/testbed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ pub(crate) fn maybe_load_device(
config_dir: &Path,
access: &DeviceAccessStrategy,
) -> Option<Result<Arc<LocalDevice>, LoadDeviceError>> {
log::trace!(
"Trying to load device from testbed (cfg={cfg}, access={access:?})",
cfg = config_dir.display()
);
test_get_testbed_component_store::<ComponentStore>(config_dir, STORE_ENTRY_KEY, store_factory)
.and_then(|store| {
// 1) Try to load from the cache
Expand Down
3 changes: 2 additions & 1 deletion libparsec/crates/platform_storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ libsqlite3-sys = { workspace = true, features = ["bundled"] }
sqlx = { workspace = true, features = ["sqlite", "runtime-tokio", "macros"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
indexed_db_futures = { workspace = true, features = ["indices", "cursors"] }
indexed-db = { workspace = true }
indexed_db_futures = { workspace = true, features = ["indices", "cursors", "serde", "streams"] }
js-sys = { workspace = true }
web-sys = { workspace = true, features = ["IdbKeyRange"] }
serde = { workspace = true }
Expand Down
73 changes: 51 additions & 22 deletions libparsec/crates/platform_storage/src/web/certificates.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

#![allow(unused_variables)]

use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;

use indexed_db_futures::prelude::IdbTransaction;
use indexed_db_futures::IdbDatabase;
use indexed_db_futures::{database::Database, transaction::Transaction};
use libparsec_types::prelude::*;

use crate::certificates::{
Expand All @@ -19,20 +16,34 @@ use crate::web::DB_VERSION;

#[derive(Debug)]
pub(crate) struct PlatformCertificatesStorageForUpdateGuard<'a> {
transaction: IdbTransaction<'a>,
transaction: Option<Transaction<'a>>,
}

impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
pub async fn commit(self) -> anyhow::Result<()> {
super::db::commit(self.transaction).await
fn get_transaction(&self) -> &Transaction<'a> {
self.transaction
.as_ref()
.expect("Transaction already committed or dropped")
}

pub async fn commit(mut self) -> anyhow::Result<()> {
log::debug!(concat!(
stringify!(PlatformCertificatesStorageForUpdateGuard),
" Committing transaction"
));
let Some(transaction) = self.transaction.take() else {
panic!("Transaction already committed or dropped")
};
super::db::commit(transaction).await
}

pub async fn get_certificate_encrypted<'b>(
&mut self,
query: GetCertificateQuery<'b>,
up_to: UpTo,
) -> Result<(DateTime, Vec<u8>), GetCertificateError> {
let certifs = Certificate::get_values(&self.transaction, CertificateFilter(query)).await?;
let certifs =
Certificate::get_values(self.get_transaction(), CertificateFilter(query)).await?;

let maybe_certif_timestamp = certifs
.get(0)
Expand Down Expand Up @@ -64,7 +75,7 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
};

// Determine if the result is an actual success or a ExistButTooRecent error
if let Some((certif_timestamp, certif)) = maybe_certif_timestamp {
if let Some((certif_timestamp, _certif)) = maybe_certif_timestamp {
let certificate_timestamp = DateTime::from_timestamp_micros(certif_timestamp)
.map_err(|err| GetCertificateError::Internal(err.into()))?;

Expand All @@ -86,7 +97,8 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
offset: Option<u32>,
limit: Option<u32>,
) -> anyhow::Result<Vec<(DateTime, Vec<u8>)>> {
let certifs = Certificate::get_values(&self.transaction, CertificateFilter(query)).await?;
let certifs =
Certificate::get_values(&self.get_transaction(), CertificateFilter(query)).await?;

let mut certifs = if let UpTo::Timestamp(up_to) = up_to {
certifs
Expand Down Expand Up @@ -116,7 +128,7 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
}

pub async fn forget_all_certificates(&mut self) -> anyhow::Result<()> {
Certificate::clear(&self.transaction).await
Certificate::clear(self.get_transaction()).await
}

pub async fn add_certificate(
Expand Down Expand Up @@ -147,7 +159,7 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
filter1,
filter2,
},
&self.transaction,
self.get_transaction(),
)
.await
}
Expand All @@ -157,10 +169,12 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
let mut sequester_last_timestamp = None;
let mut per_realm_last_timestamps = HashMap::new();
let mut shamir_recovery_last_timestamp = None;
let transaction = self.get_transaction();

for ty in <CommonTopicArcCertificate as StorableCertificateTopic>::TYPES {
log::trace!("get_last_timestamps: fetch common certifs of type {ty}");
let certifs = Certificate::get_values(
&self.transaction,
transaction,
CertificateFilter(GetCertificateQuery::NoFilter {
certificate_type: ty,
}),
Expand All @@ -178,8 +192,9 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
}

for ty in <SequesterTopicArcCertificate as StorableCertificateTopic>::TYPES {
log::trace!("get_last_timestamps: fetch sequester certifs of type {ty}");
let certifs = Certificate::get_values(
&self.transaction,
transaction,
CertificateFilter(GetCertificateQuery::NoFilter {
certificate_type: ty,
}),
Expand All @@ -197,8 +212,9 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
}

for ty in <RealmTopicArcCertificate as StorableCertificateTopic>::TYPES {
log::trace!("get_last_timestamps: fetch realm certifs of type {ty}");
let certifs = Certificate::get_values(
&self.transaction,
transaction,
CertificateFilter(GetCertificateQuery::NoFilter {
certificate_type: ty,
}),
Expand All @@ -224,8 +240,9 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
}

for ty in <ShamirRecoveryTopicArcCertificate as StorableCertificateTopic>::TYPES {
log::trace!("get_last_timestamps: fetch shamir certifs of type {ty}");
let certifs = Certificate::get_values(
&self.transaction,
transaction,
CertificateFilter(GetCertificateQuery::NoFilter {
certificate_type: ty,
}),
Expand Down Expand Up @@ -258,16 +275,28 @@ impl<'a> PlatformCertificatesStorageForUpdateGuard<'a> {
}
}

impl Drop for PlatformCertificatesStorageForUpdateGuard<'_> {
fn drop(&mut self) {
if self.transaction.is_some() {
log::debug!(concat!(
stringify!(PlatformCertificatesStorageForUpdateGuard),
" Dropping transaction without commit"
));
}
}
}

#[derive(Debug)]
pub(crate) struct PlatformCertificatesStorage {
conn: Arc<IdbDatabase>,
conn: Arc<Database>,
}

// Safety: PlatformCertificatesStorage is read only
unsafe impl Send for PlatformCertificatesStorage {}

impl PlatformCertificatesStorage {
pub async fn no_populate_start(
#[cfg_attr(not(feature = "test-with-testbed"), allow(unused_variables))]
data_base_dir: &Path,
device: &LocalDevice,
) -> anyhow::Result<Self> {
Expand All @@ -276,15 +305,14 @@ impl PlatformCertificatesStorage {
#[cfg(feature = "test-with-testbed")]
let name = format!(
"{}-{}-certificates",
data_base_dir.to_str().unwrap(),
data_base_dir.display(),
device.device_id.hex()
);

#[cfg(not(feature = "test-with-testbed"))]
let name = format!("{}-certificates", device.device_id.hex());

let db_req =
IdbDatabase::open_u32(&name, DB_VERSION).map_err(|e| anyhow::anyhow!("{e:?}"))?;
let db_req = Database::open(&name).with_version(DB_VERSION);

// 2) Initialize the database (if needed)

Expand All @@ -297,15 +325,16 @@ impl PlatformCertificatesStorage {
}

pub async fn stop(self) -> anyhow::Result<()> {
self.conn.close();
// TODO: Should we wrap the connection in an Option to be able to take the value on close?
self.conn.as_ref().clone().close();
Ok(())
}

pub async fn for_update(
&mut self,
) -> anyhow::Result<PlatformCertificatesStorageForUpdateGuard> {
Ok(PlatformCertificatesStorageForUpdateGuard {
transaction: Certificate::write(&self.conn)?,
transaction: Some(Certificate::write(&self.conn)?),
})
}

Expand Down
Loading
Loading