use crate::ed25519::PublicKey;
use crate::public_key_hashable::PublicKeyHashable;
use crate::revoke::Revoke;
use crate::trust::Trust;
use failure::_core::time::Duration;
use std::collections::HashMap;
#[derive(Debug, Clone)]
enum TrustRelation {
Auth(Auth),
Revoke(Revoke),
}
#[derive(Debug, Clone)]
pub struct Auth {
pub trust: Trust,
pub issued_by: PublicKey,
}
#[derive(Debug)]
pub struct TrustNode {
pub pk: PublicKey,
trust_relations: HashMap<PublicKeyHashable, TrustRelation>,
pub verified_at: Duration,
}
#[allow(dead_code)]
impl TrustNode {
pub fn new(pk: PublicKey, verified_at: Duration) -> Self {
Self {
pk,
trust_relations: HashMap::new(),
verified_at,
}
}
pub fn get_auth(&self, pk: PublicKey) -> Option<Auth> {
match self.trust_relations.get(&pk.into()) {
Some(TrustRelation::Auth(auth)) => Some(auth.clone()),
_ => None,
}
}
pub fn get_revoke(&self, pk: PublicKey) -> Option<Revoke> {
match self.trust_relations.get(&pk.into()) {
Some(TrustRelation::Revoke(rev)) => Some(rev.clone()),
_ => None,
}
}
pub fn authorizations(&self) -> impl Iterator<Item = &Auth> + '_ {
self.trust_relations.values().filter_map(|tr| {
if let TrustRelation::Auth(auth) = tr {
Some(auth)
} else {
None
}
})
}
pub fn revocations(&self) -> impl Iterator<Item = &Revoke> + '_ {
self.trust_relations.values().filter_map(|tr| {
if let TrustRelation::Revoke(revoke) = tr {
Some(revoke)
} else {
None
}
})
}
pub fn update_auth(&mut self, auth: Auth) {
let issued_by: PublicKeyHashable = auth.issued_by.clone().into();
let issued_at = auth.trust.issued_at;
self.update_relation(TrustRelation::Auth(auth), issued_at, issued_by);
}
fn insert(&mut self, pk: PublicKeyHashable, tr: TrustRelation) {
self.trust_relations.insert(pk, tr);
}
fn update_relation(
&mut self,
relation: TrustRelation,
revoked_at: Duration,
revoked_by: PublicKeyHashable,
) {
match self.trust_relations.get(&revoked_by) {
Some(TrustRelation::Auth(auth)) => {
if auth.trust.issued_at < revoked_at {
self.insert(revoked_by, relation)
}
}
Some(TrustRelation::Revoke(existed_revoke)) => {
if existed_revoke.revoked_at < revoked_at {
self.insert(revoked_by, relation)
}
}
None => self.insert(revoked_by, relation),
};
}
pub fn update_revoke(&mut self, revoke: Revoke) {
let revoked_at = revoke.revoked_at;
let revoked_by = revoke.revoked_by.clone().into();
self.update_relation(TrustRelation::Revoke(revoke), revoked_at, revoked_by);
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use crate::key_pair::KeyPair;
use super::*;
#[test]
fn test_auth_and_revoke_trust_node() {
let kp = KeyPair::generate();
let now = Duration::new(50, 0);
let past = Duration::new(5, 0);
let future = Duration::new(500, 0);
let mut trust_node = TrustNode {
pk: kp.public_key().clone(),
trust_relations: HashMap::new(),
verified_at: now,
};
let truster = KeyPair::generate();
let revoke = Revoke::create(&truster, kp.public_key(), now);
trust_node.update_revoke(revoke);
assert!(trust_node.get_revoke(truster.public_key()).is_some());
let old_trust = Trust::create(&truster, kp.public_key(), Duration::new(60, 0), past);
let old_auth = Auth {
trust: old_trust,
issued_by: truster.public_key(),
};
trust_node.update_auth(old_auth);
assert!(trust_node.get_revoke(truster.public_key()).is_some());
assert!(trust_node.get_auth(truster.public_key()).is_none());
let trust = Trust::create(&truster, kp.public_key(), Duration::new(60, 0), future);
let auth = Auth {
trust,
issued_by: truster.public_key(),
};
trust_node.update_auth(auth);
assert!(trust_node.get_auth(truster.public_key()).is_some());
assert!(trust_node.get_revoke(truster.public_key()).is_none());
}
}