Skip to content

Commit

Permalink
Sync result (#547)
Browse files Browse the repository at this point in the history
* Remove sync_account() returns MergeOutcome.

* Remove execute_sync() returns Option<MergeOutcome>.

* Split sync traits for single remote and multiple remotes.

* Use enum for remote sync result.

* Use RemoteResult in listen channel.

* Bump sos-net version, prepare for next release.

* Use type def for RemoteResult.

* Include Origin in RemoteResult.

* Prefer named fields for RemoteResult.

* Define SyncResult.

* Update sdk crate types to NetworkResult.

* Update net crate to use SyncResult type.

* Update sos cli for new SyncResult type.

* Update test specs.

* Bump minor version, prepare for next release.

* Remove obsolete into_option() function.

* Remove SyncError type.

* Add has_errors() and first_error_ref().

* Rename to has_error().

* Update dependencies.
  • Loading branch information
tmpfs authored Aug 21, 2024
1 parent 9f9fa71 commit f1403a6
Show file tree
Hide file tree
Showing 67 changed files with 645 additions and 599 deletions.
188 changes: 113 additions & 75 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/account_extras/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sos-account-extras"
version = "0.14.5"
version = "0.15.0"
edition = "2021"
description = "Extra features for Save Our Secrets local accounts."
homepage = "https://saveoursecrets.com"
Expand All @@ -21,7 +21,7 @@ tokio.workspace = true
once_cell.workspace = true

[dependencies.sos-sdk]
version = "0.14.5"
version = "0.15"
path = "../sdk"

[build-dependencies]
Expand Down
1 change: 0 additions & 1 deletion crates/integration_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pretty_assertions = "1.4"
anticipate-runner = { version = "0.5.1" }

[dev-dependencies.sos-net]
version = "0.14.0"
features = ["full"]
path = "../net"

8 changes: 3 additions & 5 deletions crates/integration_tests/tests/access_control/allow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::test_utils::{
};
use http::StatusCode;
use sos_net::{
protocol::SyncError, sdk::prelude::*, Error as ClientError,
NetworkAccount, RemoteSync,
sdk::prelude::*, AccountSync, Error as ClientError, NetworkAccount,
};

use sos_server::AccessControlConfig;
Expand Down Expand Up @@ -52,10 +51,9 @@ async fn access_control_allow() -> Result<()> {
allowed.owner.add_server(origin.clone()).await?;
denied.add_server(origin.clone()).await?;

assert!(allowed.owner.sync().await.is_none());
assert!(allowed.owner.sync().await.first_error().is_none());
let sync_error = denied.sync().await;
if let Some(SyncError { mut errors }) = sync_error {
let (_, err) = errors.remove(0);
if let Some(err) = sync_error.first_error() {
assert!(matches!(
err,
ClientError::ResponseCode(StatusCode::FORBIDDEN)
Expand Down
8 changes: 3 additions & 5 deletions crates/integration_tests/tests/access_control/deny.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::test_utils::{
};
use http::StatusCode;
use sos_net::{
protocol::SyncError, sdk::prelude::*, Error as ClientError,
NetworkAccount, RemoteSync,
sdk::prelude::*, AccountSync, Error as ClientError, NetworkAccount,
};

use sos_server::AccessControlConfig;
Expand Down Expand Up @@ -51,10 +50,9 @@ async fn access_control_deny() -> Result<()> {

allowed.owner.add_server(origin.clone()).await?;
denied.add_server(origin.clone()).await?;
assert!(allowed.owner.sync().await.is_none());
assert!(allowed.owner.sync().await.first_error().is_none());
let sync_error = denied.sync().await;
if let Some(SyncError { mut errors }) = sync_error {
let (_, err) = errors.remove(0);
if let Some(err) = sync_error.first_error() {
assert!(matches!(
err,
ClientError::ResponseCode(StatusCode::FORBIDDEN)
Expand Down
14 changes: 7 additions & 7 deletions crates/integration_tests/tests/auto_merge/create_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::test_utils::{
teardown,
};
use anyhow::Result;
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests making conflicting changes to a folder whilst
/// a server is offline and resolving the conflicts with
Expand Down Expand Up @@ -35,15 +35,15 @@ async fn auto_merge_create_secrets() -> Result<()> {
.owner
.create_secret(meta, secret, Default::default())
.await?;
assert!(result1.sync_error.is_some());
assert!(result1.sync_result.first_error().is_some());

// Create a secret on second device and fail to sync
let (meta, secret) = mock::note("note_2", "offline_secret_2");
let result2 = device2
.owner
.create_secret(meta, secret, Default::default())
.await?;
assert!(result2.sync_error.is_some());
assert!(result2.sync_result.first_error().is_some());

let device1_folder_state =
device1.owner.commit_state(&default_folder).await?;
Expand All @@ -59,12 +59,12 @@ async fn auto_merge_create_secrets() -> Result<()> {
let _server = spawn(TEST_ID, Some(addr), None).await?;

// Sync the first device
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

// Sync the second device which will auto merge local
// changes with the remote so it has both secrets
let sync_error = device2.owner.sync().await;
assert!(sync_error.is_none());
let sync_result = device2.owner.sync().await;
assert!(sync_result.first_error().is_none());

// Second device now has both secrets
let (s1, _) = device2
Expand Down Expand Up @@ -94,7 +94,7 @@ async fn auto_merge_create_secrets() -> Result<()> {

// Sync the first device again to fetch the remote commits
// that were changed when the auto merge executed
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

// First device now has both secrets
let (s1, _) = device1
Expand Down
17 changes: 8 additions & 9 deletions crates/integration_tests/tests/auto_merge/delete_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::test_utils::{
teardown,
};
use anyhow::Result;
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests making deletes to a folder whilst
/// a server is offline and resolving the conflicts with
Expand All @@ -30,7 +30,7 @@ async fn auto_merge_delete_secrets() -> Result<()> {
.owner
.create_secret(meta, secret, Default::default())
.await?;
assert!(result1.sync_error.is_none());
assert!(result1.sync_result.first_error().is_none());

// Create a secret (device2) which will auto merge
//
Expand All @@ -43,8 +43,7 @@ async fn auto_merge_delete_secrets() -> Result<()> {
.owner
.create_secret(meta, secret, Default::default())
.await?;
println!("{:#?}", result2.sync_error);
assert!(result2.sync_error.is_none());
assert!(result2.sync_result.first_error().is_none());

// Oh no, the server has gone offline!
drop(server);
Expand All @@ -56,14 +55,14 @@ async fn auto_merge_delete_secrets() -> Result<()> {
.owner
.delete_secret(&result1.id, Default::default())
.await?;
assert!(result.sync_error.is_some());
assert!(result.sync_result.first_error().is_some());

// Second device deletes it's secret
let result = device2
.owner
.delete_secret(&result2.id, Default::default())
.await?;
assert!(result.sync_error.is_some());
assert!(result.sync_result.first_error().is_some());

let device1_folder_state =
device1.owner.commit_state(&default_folder).await?;
Expand All @@ -83,13 +82,13 @@ async fn auto_merge_delete_secrets() -> Result<()> {
// This brings the first client and server into sync
// with both create secrets and the deletion on the
// first client but the second client is out of sync.
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

// Sync second device to auto merge and push their offline changes
assert!(device2.owner.sync().await.is_none());
assert!(device2.owner.sync().await.first_error().is_none());

// Sync first device again to fetch the pushed changes
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

// Folder commits are back in sync
let device1_folder_state =
Expand Down
20 changes: 10 additions & 10 deletions crates/integration_tests/tests/auto_merge/edit_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::test_utils::{
teardown,
};
use anyhow::Result;
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests making conflicting edits to a folder whilst
/// a server is offline and resolving the conflicts with
Expand All @@ -30,10 +30,10 @@ async fn auto_merge_edit_secrets() -> Result<()> {
.owner
.create_secret(meta, secret, Default::default())
.await?;
assert!(result.sync_error.is_none());
assert!(result.sync_result.first_error().is_none());

// Sync to fetch the new secret on the second device
assert!(device2.owner.sync().await.is_none());
assert!(device2.owner.sync().await.first_error().is_none());

// Oh no, the server has gone offline!
drop(server);
Expand All @@ -42,7 +42,7 @@ async fn auto_merge_edit_secrets() -> Result<()> {

// Update the secret whilst offline on first device
let (meta, secret) = mock::note("edit_1", TEST_ID);
let SecretChange { sync_error, .. } = device1
let SecretChange { sync_result, .. } = device1
.owner
.update_secret(
&result.id,
Expand All @@ -52,11 +52,11 @@ async fn auto_merge_edit_secrets() -> Result<()> {
None,
)
.await?;
assert!(sync_error.is_some());
assert!(sync_result.first_error().is_some());

// Update the secret whilst offline on second device
let (meta, secret) = mock::note("edit_2", TEST_ID);
let SecretChange { sync_error, .. } = device2
let SecretChange { sync_result, .. } = device2
.owner
.update_secret(
&result.id,
Expand All @@ -66,7 +66,7 @@ async fn auto_merge_edit_secrets() -> Result<()> {
None,
)
.await?;
assert!(sync_error.is_some());
assert!(sync_result.first_error().is_some());

let device1_folder_state =
device1.owner.commit_state(&default_folder).await?;
Expand All @@ -82,13 +82,13 @@ async fn auto_merge_edit_secrets() -> Result<()> {
let _server = spawn(TEST_ID, Some(addr), None).await?;

// Sync first device to push changes
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

// Sync second device to auto merge
assert!(device2.owner.sync().await.is_none());
assert!(device2.owner.sync().await.first_error().is_none());

// Sync first device again to fetch auto merged changes
assert!(device1.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());

let device1_folder_state =
device1.owner.commit_state(&default_folder).await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/integration_tests/tests/auto_merge/scan_commits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async fn auto_merge_scan_commits() -> Result<()> {
.owner
.create_secret(meta, secret, Default::default())
.await?;
assert!(result.sync_error.is_none());
assert!(result.sync_result.first_error().is_none());
let (meta, secret) = mock::note("note_edited", TEST_ID);
device
.owner
Expand Down
4 changes: 2 additions & 2 deletions crates/integration_tests/tests/file_transfers/multi_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::test_utils::{
mock::files::{create_file_secret, update_file_secret},
simulate_device, spawn, teardown, wait_for_num_transfers,
};
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests uploading an external file to multiple servers.
#[tokio::test]
Expand Down Expand Up @@ -295,7 +295,7 @@ async fn file_transfers_multi_download() -> Result<()> {
{
// Sync pulls down the file event logs and
// creates the pending download transfer operation
assert!(downloader.owner.sync().await.is_none());
assert!(downloader.owner.sync().await.first_error().is_none());
wait_for_num_transfers(&downloader.owner, 1).await?;

let server1_path = downloader.server_path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::test_utils::{
mock::files::{create_file_secret, update_file_secret},
simulate_device, spawn, teardown, wait_for_file, wait_for_file_not_exist,
};
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests uploading an external file to multiple servers
/// when the first server is offline.
Expand Down Expand Up @@ -388,8 +388,8 @@ async fn file_transfers_offline_multi_download() -> Result<()> {
//
// We have an error here as the first server will fail
// to connect for the sync.
let sync_error = downloader.owner.sync().await;
assert!(sync_error.is_none());
let sync_result = downloader.owner.sync().await;
assert!(sync_result.first_error().is_none());

// Wait for the file to exist
let paths = downloader.owner.paths();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::test_utils::{
mock::files::{create_file_secret, update_file_secret},
simulate_device, spawn, teardown, wait_for_num_transfers,
};
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests uploading an external file.
#[tokio::test]
Expand Down Expand Up @@ -266,7 +266,7 @@ async fn file_transfers_single_download() -> Result<()> {
{
// Sync pulls down the file event logs and
// creates the pending download transfer operation
assert!(downloader.owner.sync().await.is_none());
assert!(downloader.owner.sync().await.first_error().is_none());

wait_for_num_transfers(&downloader.owner, 1).await?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::test_utils::{
simulate_device_with_builder, spawn, teardown,
};
use anyhow::Result;
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests moving to and from an archive folder.
#[tokio::test]
Expand Down Expand Up @@ -35,8 +35,8 @@ async fn network_sync_archive_unarchive() -> Result<()> {
.await?;

// Sync so they both have the secret
assert!(device1.owner.sync().await.is_none());
assert!(device2.owner.sync().await.is_none());
assert!(device1.owner.sync().await.first_error().is_none());
assert!(device2.owner.sync().await.first_error().is_none());

// Move to the archive
let SecretMove { id: secret_id, .. } = device1
Expand All @@ -52,7 +52,7 @@ async fn network_sync_archive_unarchive() -> Result<()> {
assert_eq!(1, num_events(&mut device2.owner, archive_folder.id()).await);

// Second client syncs
assert!(device2.owner.sync().await.is_none());
assert!(device2.owner.sync().await.first_error().is_none());

// Events should be in sync now
assert_eq!(3, num_events(&mut device1.owner, default_folder.id()).await);
Expand Down Expand Up @@ -81,7 +81,7 @@ async fn network_sync_archive_unarchive() -> Result<()> {
assert_eq!(2, num_events(&mut device2.owner, archive_folder.id()).await);

// Second client syncs to get up to date
assert!(device2.owner.sync().await.is_none());
assert!(device2.owner.sync().await.first_error().is_none());

let mut bridge = device1.owner.remove_server(&origin).await?.unwrap();
assert_local_remote_events_eq(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::test_utils::{mock, simulate_device, spawn, teardown};
use anyhow::Result;
use sos_net::{sdk::prelude::*, RemoteSync};
use sos_net::{sdk::prelude::*, AccountSync};

/// Tests syncing an authenticator folder after
/// disabling the NO_SYNC flag.
Expand Down Expand Up @@ -36,8 +36,8 @@ async fn network_authenticator_sync() -> Result<()> {
.await?;

// Desktop syncs before NO_SYNC flag has been removed
let sync_error = desktop.owner.sync().await;
assert!(sync_error.is_none());
let sync_result = desktop.owner.sync().await;
assert!(sync_result.first_error().is_none());

// Try to read the secret but can't as the server
// will not send events when NO_SYNC is set
Expand All @@ -57,8 +57,8 @@ async fn network_authenticator_sync() -> Result<()> {
.await?;

// Sync the account on the desktop device
let sync_error = desktop.owner.sync().await;
assert!(sync_error.is_none());
let sync_result = desktop.owner.sync().await;
assert!(sync_result.first_error().is_none());

// Should be able to read the TOTP on the synced desktop device
let (data, _) =
Expand Down
Loading

0 comments on commit f1403a6

Please sign in to comment.