132 lines
4 KiB
Rust
132 lines
4 KiB
Rust
use iota_identity::{
|
|
AuthorityKind, LocalNodeIdentity, LocalUserDescriptor, LocalUserId, PrincipalHome, PrincipalId,
|
|
PrincipalStore, VerifiedPrincipalDescriptor,
|
|
};
|
|
use iota_storage::identity::SqlitePrincipalStore;
|
|
use mtp::crypto::Keyring;
|
|
|
|
#[test]
|
|
fn local_descriptor_revision_persists_changes_and_retirement() {
|
|
let storage = tempfile::tempdir().unwrap();
|
|
iota_util::file_util::configure_storage_directory(storage.path().to_owned());
|
|
iota_storage::util::db::initialize_database().unwrap();
|
|
|
|
let identity = LocalNodeIdentity::from_keyring(Keyring::generate()).unwrap();
|
|
let user_key = Keyring::generate();
|
|
let mut user = LocalUserDescriptor {
|
|
id: LocalUserId(9),
|
|
username: "alice".into(),
|
|
display_name: None,
|
|
public_key: user_key.public_key_bundle().try_to_base64().unwrap(),
|
|
};
|
|
iota_storage::util::db::with_db(|connection| {
|
|
connection.execute(
|
|
"INSERT INTO users (user_id, username, public_key, created_at) VALUES (?1, ?2, ?3, ?4)",
|
|
rusqlite::params![user.id.0, user.username, user.public_key, 1_i64],
|
|
)?;
|
|
Ok(())
|
|
})
|
|
.unwrap();
|
|
|
|
let store = SqlitePrincipalStore;
|
|
let home = PrincipalHome::Iota(identity.node_id().clone());
|
|
store
|
|
.ensure_local_principal(
|
|
identity.authority_id(),
|
|
AuthorityKind::Iota,
|
|
&user,
|
|
home.clone(),
|
|
1_000,
|
|
)
|
|
.unwrap();
|
|
let first = store.local_principal_descriptor(user.id).unwrap();
|
|
assert_eq!(first.revision, 0);
|
|
|
|
store
|
|
.ensure_local_principal(
|
|
identity.authority_id(),
|
|
AuthorityKind::Iota,
|
|
&user,
|
|
home.clone(),
|
|
1_001,
|
|
)
|
|
.unwrap();
|
|
assert_eq!(
|
|
store.local_principal_descriptor(user.id).unwrap().revision,
|
|
0
|
|
);
|
|
|
|
user.display_name = Some("Alice".into());
|
|
store
|
|
.ensure_local_principal(
|
|
identity.authority_id(),
|
|
AuthorityKind::Iota,
|
|
&user,
|
|
home.clone(),
|
|
1_002,
|
|
)
|
|
.unwrap();
|
|
assert_eq!(
|
|
store.local_principal_descriptor(user.id).unwrap().revision,
|
|
1
|
|
);
|
|
|
|
let replacement_key = Keyring::generate().public_key_bundle();
|
|
user.public_key = replacement_key.try_to_base64().unwrap();
|
|
store
|
|
.ensure_local_principal(
|
|
identity.authority_id(),
|
|
AuthorityKind::Iota,
|
|
&user,
|
|
home.clone(),
|
|
1_003,
|
|
)
|
|
.unwrap();
|
|
let rotated = store.local_principal_descriptor(user.id).unwrap();
|
|
assert_eq!(rotated.revision, 2);
|
|
assert_eq!(rotated.public_keys.len(), 1);
|
|
assert_eq!(
|
|
rotated.public_keys[0].try_to_base64().unwrap(),
|
|
replacement_key.try_to_base64().unwrap()
|
|
);
|
|
|
|
let renewal_at = rotated.valid_until.unwrap() - 1;
|
|
store
|
|
.ensure_local_principal(
|
|
identity.authority_id(),
|
|
AuthorityKind::Iota,
|
|
&user,
|
|
home,
|
|
renewal_at,
|
|
)
|
|
.unwrap();
|
|
let renewed = store.local_principal_descriptor(user.id).unwrap();
|
|
assert_eq!(renewed.revision, 3);
|
|
let mut conflicting = renewed.clone();
|
|
conflicting.display_name = Some("Changed without revision".into());
|
|
assert!(
|
|
store
|
|
.upsert_remote_descriptor(
|
|
&VerifiedPrincipalDescriptor::from_trusted_authority(conflicting).unwrap()
|
|
)
|
|
.is_err()
|
|
);
|
|
|
|
store
|
|
.retire_local_principal(user.id, renewal_at + 1)
|
|
.unwrap();
|
|
assert!(store.local_principal_descriptor(user.id).is_err());
|
|
let principal = PrincipalId {
|
|
authority: identity.authority_id().clone(),
|
|
user_id: 9,
|
|
};
|
|
let retired = store.get_by_canonical_id(&principal).unwrap().unwrap();
|
|
assert_eq!(retired.descriptor_revision, 4);
|
|
assert!(
|
|
store
|
|
.upsert_remote_descriptor(
|
|
&VerifiedPrincipalDescriptor::from_trusted_authority(first).unwrap()
|
|
)
|
|
.is_err()
|
|
);
|
|
}
|