Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
fix: Ensure write access when syncing a sphere. Fixes #389
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantell committed Oct 9, 2023
1 parent 43b325c commit a625de0
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 6 deletions.
14 changes: 13 additions & 1 deletion rust/noosphere-core/src/context/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,13 @@ mod tests {
helpers::{make_valid_link_record, simulated_sphere_context},
tracing::initialize_tracing,
view::Sphere,
SphereSync, SyncError,
};

use noosphere_storage::{MemoryStorage, SphereDb};
use ucan::{builder::UcanBuilder, crypto::KeyMaterial, store::UcanJwtStore};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test;

#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

Expand Down Expand Up @@ -436,6 +436,18 @@ mod tests {
.set_petname_record("foo", records.get(1).unwrap())
.await
.is_err());
}

async fn it_requires_write_access_to_sync() -> Result<()> {
initialize_tracing(None);

let (mut sphere_context, _) =
simulated_sphere_context(SimulationAccess::Readonly, None).await?;

assert!(matches!(
sphere_context.sync(crate::SyncRecovery::None).await,
Err(SyncError::InsufficientPermission)
));
Ok(())
}
}
3 changes: 3 additions & 0 deletions rust/noosphere-core/src/context/sync/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use thiserror::Error;
/// gateway
#[derive(Error, Debug)]
pub enum SyncError {
/// The error was due to not having write access to the sphere
#[error("Insufficient permission to sync")]
InsufficientPermission,
/// The error was a conflict; this is possibly recoverable
#[error("There was a conflict during sync")]
Conflict,
Expand Down
52 changes: 47 additions & 5 deletions rust/noosphere-core/src/context/sync/write.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::data::{Link, MemoIpld};
use crate::{
authority::Authorization,
context::{
internal::SphereContextInternal, GatewaySyncStrategy, HasMutableSphereContext,
HasSphereContext, SyncError, SyncExtent, SyncRecovery,
},
data::{Link, MemoIpld},
};
use anyhow::Result;
use async_trait::async_trait;
use noosphere_storage::Storage;

use crate::context::{HasMutableSphereContext, SyncError, SyncExtent, SyncRecovery};

use crate::context::GatewaySyncStrategy;

/// Implementors of [SphereSync] are able to sychronize with a Noosphere gateway
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
Expand Down Expand Up @@ -52,6 +55,17 @@ where
) -> Result<Link<MemoIpld>, SyncError> {
debug!("Attempting to sync...");

// Check that the author has write access to sync.
// If a sphere was joined from another sphere, do not check,
// but allow sync to proceed, as the local sphere does not have
// local proof until after initial sync. If truly no write access is
// available, the gateway will reject this sync.
if !is_sphere_joined(self).await {
self.assert_write_access()
.await
.map_err(|_| SyncError::InsufficientPermission)?;
}

let sync_strategy = GatewaySyncStrategy::default();

let version = match recovery {
Expand Down Expand Up @@ -94,3 +108,31 @@ where
Ok(version)
}
}

/// Given a `HasSphereContext<S>`, return a boolean indicating
/// whether or not this sphere has been joined from another sphere
/// (e.g. possibly lacking local authorization until syncing with a gateway).
async fn is_sphere_joined<C, S>(context: &C) -> bool
where
C: HasSphereContext<S>,
S: Storage + 'static,
{
let context = {
let context = context.sphere_context().await;
if context.is_err() {
return false;
}
context.unwrap()
};

let author = context.author();

let auth = {
let auth = author.require_authorization();
if auth.is_err() {
return false;
}
auth.unwrap()
};
matches!(auth, Authorization::Cid(_))
}

0 comments on commit a625de0

Please sign in to comment.