Skip to content

Commit

Permalink
fix: actually create subspace capability
Browse files Browse the repository at this point in the history
also adds a test (written by @voronar33, thanks!)
  • Loading branch information
Frando committed Aug 29, 2024
1 parent 81c562f commit 01982ff
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 12 deletions.
6 changes: 6 additions & 0 deletions iroh-willow/src/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ impl EntryForm {
payload: PayloadForm::Bytes(payload.into()),
}
}

/// Sets the subspace for the entry.
pub fn subspace(mut self, subspace: SubspaceId) -> Self {
self.subspace_id = SubspaceForm::Exact(subspace);
self
}
}

/// Select which capability to use for authenticating a new entry.
Expand Down
28 changes: 17 additions & 11 deletions iroh-willow/src/store/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use crate::{
data_model::WriteCapability,
grouping::AreaOfInterest,
keys::{NamespaceId, UserId},
meadowcap::{AccessMode, FailedDelegationError, McCapability, ReadAuthorisation},
meadowcap::{
AccessMode, FailedDelegationError, McCapability, McSubspaceCapability,
ReadAuthorisation,
},
},
store::traits::{CapsStorage, SecretStorage, SecretStoreError, Storage},
};
Expand Down Expand Up @@ -126,12 +129,6 @@ impl<S: Storage> Auth<S> {
namespace_id: NamespaceId,
user_id: UserId,
) -> Result<[CapabilityPack; 2], AuthError> {
// let namespace_key = namespace_id
// .into_public_key()
// .map_err(|_| AuthError::InvalidNamespaceId(namespace_id))?;
// let user_key: UserPublicKey = user_id
// .into_public_key()
// .map_err(|_| AuthError::InvalidUserId(user_id))?;
let read_cap = self.create_read_cap(namespace_id, user_id)?;
let write_cap = self.create_write_cap(namespace_id, user_id)?;
let pack = [read_cap, write_cap];
Expand All @@ -145,16 +142,25 @@ impl<S: Storage> Auth<S> {
user_key: UserId,
) -> Result<CapabilityPack, AuthError> {
let cap = if namespace_key.is_communal() {
McCapability::new_communal(namespace_key, user_key, AccessMode::Read)?
let read_cap = McCapability::new_communal(namespace_key, user_key, AccessMode::Read)?;
ReadAuthorisation::new(read_cap, None)
} else {
let namespace_secret = self
.secrets
.get_namespace(&namespace_key)
.ok_or(AuthError::MissingNamespaceSecret(namespace_key))?;
McCapability::new_owned(namespace_key, &namespace_secret, user_key, AccessMode::Read)?
let read_cap = McCapability::new_owned(
namespace_key,
&namespace_secret,
user_key,
AccessMode::Read,
)?;
let subspace_cap =
McSubspaceCapability::new(namespace_key, &namespace_secret, user_key)
.map_err(AuthError::SubspaceCapDelegationFailed)?;
ReadAuthorisation::new(read_cap, Some(subspace_cap))
};
// TODO: Subspace capability.
let pack = CapabilityPack::Read(ReadAuthorisation::new(cap, None));
let pack = CapabilityPack::Read(cap);
Ok(pack)
}

Expand Down
59 changes: 58 additions & 1 deletion iroh-willow/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ use futures_lite::StreamExt;
use iroh_blobs::store::{Map, MapEntry};
use iroh_io::AsyncSliceReaderExt;
use iroh_willow::{
interest::{Interests, IntoAreaOfInterest},
form::EntryForm,
interest::{CapSelector, DelegateTo, Interests, IntoAreaOfInterest, RestrictArea},
proto::{
data_model::{Path, PathExt},
grouping::{Area, AreaExt, Range3d},
keys::NamespaceKind,
},
session::{
intents::{Completion, EventKind},
SessionInit, SessionMode,
},
};
use meadowcap::AccessMode;

use self::util::{create_rng, insert, setup_and_delegate, spawn_two, Peer};

Expand Down Expand Up @@ -276,6 +279,60 @@ async fn peer_manager_twoway_loop() -> Result<()> {
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn owned_namespace_subspace_write_sync() -> Result<()> {
iroh_test::logging::setup_multithreaded();
let mut rng = create_rng("owned_namespace_subspace_write_sync");

let [alfie, betty] = spawn_two(&mut rng).await?;

let user_alfie = alfie.create_user().await?;
let user_betty = betty.create_user().await?;

let namespace_id = alfie
.create_namespace(NamespaceKind::Owned, user_alfie)
.await?;

let restriction = RestrictArea::Restrict(Area::new_subspace(user_betty));

let cap_for_betty = alfie
.delegate_caps(
CapSelector::any(namespace_id),
AccessMode::Write,
DelegateTo::new(user_betty, restriction),
)
.await?;

betty.import_caps(cap_for_betty).await?;

// Insert an entry into our subspace.
let path = Path::from_bytes(&[b"foo"])?;
let entry = EntryForm::new_bytes(namespace_id, path, "foo");
betty.insert_entry(entry, user_betty).await?;

// Make sure we cannot write into alfie's subspace.
let path = Path::from_bytes(&[b"foo"])?;
let entry = EntryForm::new_bytes(namespace_id, path, "foo").subspace(user_alfie);
assert!(betty.insert_entry(entry, user_betty).await.is_err());

// Make sure sync runs correctl.y
let init = SessionInit::new(
Interests::builder().add_full_cap(namespace_id),
SessionMode::ReconcileOnce,
);
let mut intent = alfie.sync_with_peer(betty.node_id(), init).await.unwrap();
let completion = intent.complete().await.expect("failed to complete intent");
assert_eq!(completion, Completion::Partial);
let entries: Vec<_> = alfie
.get_entries(namespace_id, Range3d::new_full())
.await?
.try_collect()
.await?;
assert_eq!(entries.len(), 1);

Ok(())
}

mod util {
use std::sync::{Arc, Mutex};

Expand Down

0 comments on commit 01982ff

Please sign in to comment.