use std::time::Duration; use credo::{ClaimBody, Credential, Credo, PermissionKind, WRITE_TO_SCOPE, SimpleCredentialSource, CredentialSource}; use futures::{ future::{self, join}, FutureExt, StreamExt, }; use litl::json; use mofo::Mofo; use caro::Remote; macro_rules! timeout { ($f:expr) => { tokio::time::timeout(Duration::from_millis(500), $f).map(|r| r.expect("Timed out")) }; } #[tokio::test] async fn can_create_context_and_scope_and_make_statement() { // traceful::init_test_trace(); let background = Mofo::new(); let credo = Credo::new("credo".to_string(), background.clone()); background .run_until(async { let initial_recipient = Credential::new_random(); let credential_source = Box::new(SimpleCredentialSource::new()); let scope = credo .create_scope( initial_recipient, vec![PermissionKind::MakeStatement { path_prefix: "test".to_string(), }], None, credential_source ) .await; let updates = scope.updates("test".to_owned()); let mut updates = updates.skip_while(|s| future::ready(s.valid_claims.len() < 8)); assert_eq!( timeout!(updates.next()).await.unwrap().valid_claims.len(), 8 ); let claim_id = scope .make_claim_after( ClaimBody::Statement { path: "test".to_string(), value: json!("hello world").into(), }, vec![], ) .await .unwrap(); let valid_claims = timeout!(updates.next()).await.unwrap().valid_claims; assert_eq!(valid_claims.len(), 9); assert!(valid_claims.contains_key(&claim_id)); assert_eq!( valid_claims.get(&claim_id).unwrap().0.body, ClaimBody::Statement { path: "test".to_string(), value: json!("hello world").into(), } ); }) .await; } #[tokio::test] async fn can_invite_other_identity_to_make_statements() { // traceful::init_test(); let background = Mofo::new(); let credo1 = Credo::new("credo1".to_string(), background.clone()); let credo2 = Credo::new("credo2".to_string(), background.clone()); background .run_until(async { let (credo1_as_remote, credo2_as_remote) = Remote::new_connected_test_pair("credo1", "credo2"); credo1.add_remote(credo2_as_remote).await; credo2.add_remote(credo1_as_remote).await; let initial_recipient = Credential::new_random(); let credential_source = Box::new(SimpleCredentialSource::new()); let scope1 = credo1 .create_scope( initial_recipient, vec![PermissionKind::Delegate { delegated: Box::new(PermissionKind::MakeStatement { path_prefix: "test".to_string(), }), }], None, credential_source ) .await; let updates = scope1.updates("credo1_listener".to_owned()); let invitee = Credential::new_random(); let mut updates = updates.skip_while(|s| future::ready(s.valid_claims.len() < 8)); assert_eq!( timeout!(updates.next()).await.unwrap().valid_claims.len(), 8 ); scope1 .make_claim( ClaimBody::AddSharedSecretRecipient { secret_kind: WRITE_TO_SCOPE.to_owned(), recipient: invitee.for_accepting_secrets.pub_id(), }, ) .await .unwrap(); scope1 .re_reveal_shared_secret( WRITE_TO_SCOPE) .await .unwrap(); let allow_statement_id = scope1 .make_claim( ClaimBody::Permission { to: invitee.for_making_claims.pub_id(), as_of: ti64::now(), permitted: PermissionKind::MakeStatement { path_prefix: "test".to_string(), }, }, ) .await .unwrap(); assert_eq!( timeout!(updates.next()).await.unwrap().valid_claims.len(), 9 ); assert_eq!( timeout!(updates.next()).await.unwrap().valid_claims.len(), 10 ); assert_eq!( timeout!(updates.next()).await.unwrap().valid_claims.len(), 11 ); let credential_source2 = Box::new(SimpleCredentialSource::new()); let scope2 = credo2.get_scope(&scope1.id(), credential_source2.clone_ref()); let updates2 = scope2.updates("credo2_listener".to_owned()); let mut updates2 = updates2.skip_while(|s| { println!("Got {} valid claims", s.valid_claims.len()); future::ready(s.valid_claims.len() < 11) }); assert_eq!( timeout!(updates2.next()).await.unwrap().valid_claims.len(), 11 ); credential_source2.add_credential(scope1.id(), invitee); let invitee_statement_id = scope2 .make_claim_after( ClaimBody::Statement { path: "test/a".to_string(), value: json!("Hello from invitee").into(), }, vec![allow_statement_id], ) .await .unwrap(); // println!("invitee statement: {:?}", invitee_statement_id); let (valid_claims_res, valid_claims2_res) = join(timeout!(updates.next()), timeout!(updates2.next())).await; let state = valid_claims_res.unwrap(); let state2 = valid_claims2_res.unwrap(); // println!("{:#?}", state); // println!("{:#?}", state2); assert!(state.valid_claims.contains_key(&invitee_statement_id)); assert_eq!(state.valid_claims.len(), 12); assert_eq!( state .valid_claims .get(&invitee_statement_id) .unwrap() .0 .body, ClaimBody::Statement { path: "test/a".to_string(), value: json!("Hello from invitee").into(), } ); assert_eq!(state.valid_claims, state2.valid_claims); }) .await }