use crate::test_utils::{create_app, create_random_auth_req};
use crate::{App, AppError};
use safe_authenticator::test_utils::{create_authenticator, register_app};
use safe_core::utils::test_utils::random_client;
use safe_core::{Client, CoreError};
use safe_nd::{
Error as SndError, PublicKey, SDataAddress, SDataIndex, SDataPrivUserPermissions,
SDataPubUserPermissions, SDataUser,
};
use std::collections::BTreeMap;
use xor_name::XorName;
#[tokio::test]
async fn data_created_by_an_app() -> Result<(), AppError> {
let app = create_app().await;
let name: XorName = rand::random();
let tag = 15_002;
let invalid_owner = app.client.public_key().await;
let valid_owner = app.client.owner_key().await;
match app
.client
.store_pub_sdata(name, tag, invalid_owner, BTreeMap::default())
.await
{
Err(CoreError::DataError(SndError::InvalidOwners)) => (),
Ok(_) => panic!("Unexpected success storing public sequence"),
Err(err) => panic!("Unexpected error when storing public sequence {:?}", err),
}
match app
.client
.store_priv_sdata(name, tag, invalid_owner, BTreeMap::default())
.await
{
Err(CoreError::DataError(SndError::InvalidOwners)) => (),
Ok(_) => panic!("Unexpected success storing public sequence"),
Err(err) => panic!("Unexpected error when storing public sequence {:?}", err),
}
let _ = app
.client
.store_pub_sdata(name, tag, valid_owner, BTreeMap::default())
.await?;
let _ = app
.client
.store_priv_sdata(name, tag, valid_owner, BTreeMap::default())
.await?;
Ok(())
}
#[tokio::test]
async fn managing_pub_permissions_for_an_app() -> Result<(), AppError> {
let client_app = create_app().await.client;
let app_pk = client_app.public_key().await;
let client_owner = random_client()?;
let name: XorName = rand::random();
let tag = 15_002;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(true, None),
);
let owner = client_owner.public_key().await;
let address = client_owner
.store_pub_sdata(name, tag, owner, permissions)
.await?;
let _ = client_owner.sdata_append(address, vec![1]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2, 3]).await?;
let entries = client_app
.get_sdata_range(address, (SDataIndex::FromStart(0), SDataIndex::FromEnd(0)))
.await?;
let expected_entries = vec![vec![1], vec![1, 2], vec![1, 2, 3]];
assert_eq!(entries.len(), expected_entries.len());
assert_eq!(entries, expected_entries);
let _ = client_app.sdata_append(address, vec![1, 2, 3, 4]).await?;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(true, true),
);
match client_app
.sdata_set_pub_permissions(address, permissions.clone())
.await
{
Err(CoreError::DataError(SndError::AccessDenied)) => (),
res => panic!("Unexpected result: {:?}", res),
}
let _ = client_owner
.sdata_set_pub_permissions(address, permissions)
.await?;
client_app
.sdata_append(address, vec![1, 2, 3, 4, 5])
.await?;
let entries = client_app
.get_sdata_range(address, (SDataIndex::FromStart(0), SDataIndex::FromEnd(0)))
.await?;
assert_eq!(entries.len(), 5);
Ok(())
}
#[tokio::test]
async fn managing_priv_permissions_for_an_app() -> Result<(), AppError> {
let client_app = create_app().await.client;
let app_pk = client_app.public_key().await;
let client_owner = random_client()?;
let name: XorName = rand::random();
let tag = 15_002;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(app_pk, SDataPrivUserPermissions::new(true, true, false));
let owner = client_owner.public_key().await;
let address = client_owner
.store_priv_sdata(name, tag, owner, permissions)
.await?;
let _ = client_owner.sdata_append(address, vec![1]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2, 3]).await?;
let entries = client_app
.get_sdata_range(address, (SDataIndex::FromStart(0), SDataIndex::FromEnd(0)))
.await?;
let expected_entries = vec![vec![1], vec![1, 2], vec![1, 2, 3]];
assert_eq!(entries.len(), expected_entries.len());
assert_eq!(entries, expected_entries);
let _ = client_app.sdata_append(address, vec![1, 2, 3, 4]).await?;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(app_pk, SDataPrivUserPermissions::new(true, true, true));
match client_app
.sdata_set_priv_permissions(address, permissions.clone())
.await
{
Err(CoreError::DataError(SndError::AccessDenied)) => (),
res => panic!("Unexpected result: {:?}", res),
}
let _ = client_owner
.sdata_set_priv_permissions(address, permissions)
.await?;
client_app
.sdata_append(address, vec![1, 2, 3, 4, 5])
.await?;
let entries = client_app
.get_sdata_range(address, (SDataIndex::FromStart(0), SDataIndex::FromEnd(0)))
.await?;
assert_eq!(entries.len(), 5);
Ok(())
}
#[tokio::test]
async fn restricted_access_and_deletion() -> Result<(), AppError> {
let (authenticator, _, _) = create_authenticator().await;
let auth_req = create_random_auth_req();
let auth_granted = register_app(&authenticator, &auth_req)
.await
.map_err(|_| AppError::Unexpected("failed to create registered app".to_string()))?;
let app = App::registered(auth_req.app.id, auth_granted, || ()).await?;
let client_app = app.client;
let app_pk = client_app.public_key().await;
let client_owner = random_client()?;
let name: XorName = rand::random();
let tag = 15_002;
let owner = client_owner.public_key().await;
let address = client_owner
.store_pub_sdata(name, tag, owner, BTreeMap::default())
.await?;
let _ = client_owner.sdata_append(address, vec![1]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2]).await?;
let sdata = client_app.get_sdata(address).await?;
assert!(sdata.is_pub());
assert_eq!(*sdata.address(), address);
assert_eq!(sdata.entries_index(), 2);
let mut permissions = BTreeMap::new();
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(true, None),
);
client_owner
.sdata_set_pub_permissions(address, permissions)
.await?;
match client_app.sdata_append(address, vec![1, 2, 3, 4]).await {
Err(CoreError::DataError(SndError::AccessDenied)) => (),
res => panic!("Unexpected result: {:?}", res),
}
Ok(())
}
#[tokio::test]
async fn public_permissions_with_app_restrictions() -> Result<(), AppError> {
let app = create_app().await;
let client_app = app.client.clone();
let app_pk = client_app.public_key().await;
let client_owner = random_client()?;
let name: XorName = rand::random();
let tag = 15_002;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(None, true),
);
let _ = permissions.insert(SDataUser::Anyone, SDataPubUserPermissions::new(true, None));
let owner = client_owner.public_key().await;
let address = client_owner
.store_pub_sdata(name, tag, owner, permissions)
.await?;
let _ = client_owner.sdata_append(address, vec![1]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2]).await?;
let _ = client_owner.sdata_append(address, vec![1, 2, 3]).await?;
let client_random = create_app().await.client;
let data = client_random.get_sdata(address).await?;
assert_eq!(*data.address(), address);
client_random
.sdata_append(address, vec![1, 2, 3, 4])
.await?;
let mut permissions = BTreeMap::new();
let random_app = PublicKey::from(threshold_crypto::SecretKey::random().public_key());
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(true, true),
);
let _ = permissions.insert(
SDataUser::Key(random_app),
SDataPubUserPermissions::new(true, true),
);
let _ = permissions.insert(SDataUser::Anyone, SDataPubUserPermissions::new(true, false));
client_app
.sdata_set_pub_permissions(address, permissions)
.await?;
random_app_access(address).await?;
let mut permissions = BTreeMap::new();
let _ = permissions.insert(
SDataUser::Key(app_pk),
SDataPubUserPermissions::new(false, false),
);
let _ = permissions.insert(SDataUser::Anyone, SDataPubUserPermissions::new(true, false));
client_app
.sdata_set_pub_permissions(address, permissions)
.await?;
match client_app.sdata_append(address, vec![1, 2, 3, 4, 5]).await {
Err(CoreError::DataError(SndError::AccessDenied)) => (),
res => panic!("Unexpected result: {:?}", res),
}
let permissions = BTreeMap::new();
match client_app
.sdata_set_pub_permissions(address, permissions)
.await
{
Err(CoreError::DataError(SndError::AccessDenied)) => (),
res => panic!("Unexpected result: {:?}", res),
}
let data = client_app.get_sdata(address).await?;
assert_eq!(*data.address(), address);
random_app_access(address).await?;
Ok(())
}
async fn random_app_access(address: SDataAddress) -> Result<(), AppError> {
let app = create_app().await;
let client = app.client;
let data = client.get_sdata(address).await?;
assert_eq!(*data.address(), address);
let _ = client.sdata_append(address, vec![100]).await?;
let index = data.entries_index() + 1;
let entries = client
.get_sdata_range(address, (SDataIndex::FromStart(0), SDataIndex::FromEnd(0)))
.await?;
assert_eq!(entries.len() as u64, index);
Ok(())
}