use super::Error;
use simple_crypto::{Hashable, Hash};
use super::structs::{PermissionedRecord, ProtocolFetcher};
use simple_database::database::{SortOptions, Filters, Index};
use super::permission::PermissionSet;
use crate::common::DateTime;
use super::json_rpc::JsonRpc;
use crate::dids::structs::{
DefaultDidResolver,
Did,
};
use crate::dids::traits::DidResolver;
use crate::dids::signing::Verifier;
use super::structs::{AgentKey, Record};
use super::permission::PermissionOptions;
use super::protocol::Protocol;
use super::traits::Router;
use super::{PrivateClient, PublicClient, DMClient};
use std::collections::BTreeMap;
use either::Either;
pub struct Agent {
agent_key: AgentKey,
private_client: PrivateClient,
public_client: PublicClient,
dm_client: DMClient,
}
impl Agent {
pub fn new(
agent_key: AgentKey,
protocols: BTreeMap<Hash, Protocol>,
router: Option<Box<dyn Router>>,
did_resolver: Option<Box<dyn DidResolver>>,
) -> Self {
let did_resolver = did_resolver.unwrap_or(Box::new(DefaultDidResolver::new()));
let router = router.unwrap_or(Box::new(JsonRpc::new(Some(did_resolver.clone()))));
let protocol_fetcher = ProtocolFetcher::new(protocols);
let private_client = PrivateClient::new(router.clone(), protocol_fetcher.clone());
let public_client = PublicClient::new(Either::Left(agent_key.sig_key.clone()), router.clone(), did_resolver.clone(), protocol_fetcher.clone());
let dm_client = DMClient::new(agent_key.sig_key.clone(), agent_key.com_key.key.clone(), router.clone(), did_resolver.clone());
Agent{
agent_key,
private_client,
public_client,
dm_client,
}
}
pub fn tenant(&self) -> Did {self.agent_key.sig_key.public.did.clone()}
pub async fn create(
&self,
parent_path: &[Hash],
permission_options: Option<&PermissionOptions>,
record: Record,
dids: &[&Did],
) -> Result<Vec<Hash>, Error> {
let error = |r: &str| Error::bad_request("Agent.create", r);
let record_path = [parent_path.to_vec(), vec![record.record_id]].concat();
let record_perms = self.get_permission(&record_path)?;
let child_protocol = record.protocol;
let (_, perm_parent) = self.private_client.read(&self.get_permission(parent_path)?, dids).await?.ok_or(error("Parent could not be found"))?;
let perms = self.private_client.create(record_perms, permission_options, record, dids).await?;
self.private_client.create_child(&perm_parent, &child_protocol, &perms, dids).await?;
Ok(record_path)
}
pub async fn read(
&self,
path: &[Hash],
index: Option<(usize, Option<usize>)>,
dids: &[&Did]
) -> Result<Option<Record>, Error> {
let perms = self.get_permission(path)?;
if let Some((_, record)) = self.private_client.read(&perms, dids).await? {
if let Some((start, end)) = index {
Ok(self.private_client.read_child(&record, Some(start), end, dids).await?.0.first().map(|pr| pr.2.1.clone()))
} else {
Ok(Some(record.1))
}
} else {
Ok(None)
}
}
pub async fn update(
&self,
path: &[Hash],
permission_options: Option<&PermissionOptions>,
record: Record,
dids: &[&Did],
) -> Result<(), Error> {
let perms = self.get_permission(path)?;
self.private_client.update(perms, permission_options, record, dids).await?;
Ok(())
}
pub async fn delete(
&self,
path: &[Hash],
dids: &[&Did],
) -> Result<bool, Error> {
if let Some((_, record)) = self.private_client.read(&self.get_permission(path)?, dids).await? {
self.private_client.delete(&record.0, dids).await?;
Ok(true)
} else {Ok(false)}
}
pub async fn share(
&self,
path: &[Hash],
permission_options: &PermissionOptions,
recipient: &Did
) -> Result<(), Error> {
let channel = self.establish_direct_messages(recipient).await?;
self.private_client.create_child(
&channel,
&Protocol::pointer().hash(),
&self.get_permission(path)?.subset(permission_options)?,
&[&self.tenant(), recipient]
).await?;
Ok(())
}
pub async fn scan(&self) -> Result<(), Error> {
let dids = [&self.tenant()];
self.check_did_messages().await?;
let (_, root) = self.private_client.read(&PermissionSet::from_key(&self.agent_key.com_key)?, &dids).await?
.ok_or(Error::bad_request("Agent.establish_direct_messages", "Parent Not Found"))?;
let channels = self.private_client.read_child(&root, None, None, &dids).await?.0;
for (_, _, channel, index) in channels {
let ldi_id = serde_json::to_vec(&format!("LAST_DM_INDEX: {}", index))?.hash();
let ldi_perms = PermissionSet::from_key(&self.agent_key.com_key.from_path(&[ldi_id])?)?;
let last_dm_index = self.private_client.read(&ldi_perms, &dids).await?.map(|record|
serde_json::from_slice::<usize>(&record.1.1.payload)
).transpose()?;
let (records, last_dm_index) = self.private_client.read_child(&channel, last_dm_index, None, &dids).await?;
for (channel_item, _, _, _) in records {
let sent_perms = serde_json::from_slice::<PermissionSet>(&channel_item.1.payload)?;
if let Some((_, perm_sent)) = self.private_client.read(&sent_perms, &dids).await? {
if let Ok(my_perms) = self.get_permission(&sent_perms.path) {
if let (Some(record), _) = self.private_client.internal_read(&my_perms, None, &dids).await? {
if record.1.protocol == Protocol::pointer().hash() {
let perms = serde_json::from_slice::<PermissionSet>(&record.1.payload)?;
if let Ok(perms) = perms.combine(sent_perms) {
let mut record = record.1;
record.payload = serde_json::to_vec(&perms)?;
self.private_client.update(my_perms, None, record, &dids).await?;
}
}
} else {
let parent_path = &sent_perms.path[..sent_perms.path.len()-1];
if let Ok(my_parent_perms) = self.get_permission(parent_path) {
if let Ok(Some((_, perm_parent))) = self.private_client.read(&my_parent_perms, &dids).await {
let record = Record::new(None, Protocol::pointer().hash(), serde_json::to_vec(&sent_perms)?);
let perms = self.private_client.create(my_perms, None, record, &dids).await?;
self.private_client.create_child(&perm_parent, &perm_sent.1.protocol, &perms, &dids).await?;
}
}
}
}
}
}
let record = Record::new(Some(ldi_id), Protocol::usize().hash(), serde_json::to_vec(&last_dm_index)?);
self.private_client.update(ldi_perms, None, record, &dids).await?;
}
Ok(())
}
pub async fn public_create(
&self,
record: Record,
index: Index,
dids: &[&Did]
) -> Result<(), Error> {
self.public_client.create(record, index, dids).await
}
pub async fn public_read(
&self,
filters: Filters,
sort_options: Option<SortOptions>,
dids: &[&Did]
) -> Result<Vec<(Verifier, Record)>, Error> {
self.public_client.read(filters, sort_options, dids).await
}
pub async fn public_update(
&self,
record: Record,
index: Index,
dids: &[&Did]
) -> Result<(), Error> {
self.public_client.update(record, index, dids).await
}
pub async fn public_delete(
&self,
record_id: Hash,
dids: &[&Did]
) -> Result<(), Error> {
self.public_client.delete(record_id, dids).await
}
async fn establish_direct_messages(&self, recipient: &Did) -> Result<PermissionedRecord, Error> {
self.check_did_messages().await?;
let dids = [recipient, &self.tenant()];
let perms = PermissionSet::from_key(&self.agent_key.com_key.from_path(&[recipient.hash()])?)?;
if let Some((_, perm_record)) = self.private_client.read(&perms, &dids).await? {
Ok(perm_record)
} else {
let protocol = Protocol::dms_channel();
let record = Record::new(Some(recipient.hash()), protocol.hash(), Vec::new());
let (_, perm_parent) = self.private_client.read(&PermissionSet::from_key(&self.agent_key.com_key)?, &dids).await?
.ok_or(Error::bad_request("Agent.establish_direct_messages", "Parent Not Found"))?;
let perms = self.private_client.create(perms.clone(), None, record, &dids).await?;
self.private_client.create_child(&perm_parent, &protocol.hash(), &perms, &[&self.tenant()]).await?;
self.dm_client.create(recipient, perms.clone()).await?;
Ok(self.private_client.read(&perms, &dids).await?.ok_or(
Error::bad_request("Agent.establish_direct_messages", "Could not create record")
)?.1)
}
}
async fn check_did_messages(&self) -> Result<(), Error> {
let dids = [&self.tenant()];
let ldc_id = serde_json::to_vec("LAST_DM_CHECK")?.hash();
let ldc_perms = PermissionSet::from_key(&self.agent_key.com_key.from_path(&[ldc_id])?)?;
let last_dm_check = self.private_client.read(&ldc_perms, &dids).await?.map(|record|
serde_json::from_slice::<DateTime>(&record.1.1.payload)
).transpose()?.unwrap_or_default();
for (sender, permission) in self.dm_client.read(last_dm_check).await? {
if let Some((_, pr)) = self.private_client.read(&permission, &dids).await? {
let record = Record::new(Some(sender.hash()), Protocol::pointer().hash(), serde_json::to_vec(&pr.0)?);
let channel_perms = PermissionSet::from_key(&self.agent_key.com_key.from_path(&[sender.hash()])?)?;
let (_, perm_parent) = self.private_client.read(&PermissionSet::from_key(&self.agent_key.com_key)?, &dids).await?
.ok_or(Error::bad_request("Agent.check_did_messages", "Parent Not Found"))?;
let perms = self.private_client.update(channel_perms, None, record, &dids).await?;
self.private_client.create_child(&perm_parent, &Protocol::pointer().hash(), &perms, &dids).await?;
}
}
let record = Record::new(Some(ldc_id), Protocol::date_time().hash(), serde_json::to_vec(&DateTime::now())?);
self.private_client.update(ldc_perms, None, record, &dids).await?;
Ok(())
}
fn get_permission(&self, path: &[Hash]) -> Result<PermissionSet, Error> {
PermissionSet::from_key(&self.agent_key.enc_key.from_path(path)?)
}
}
impl std::fmt::Debug for Agent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Agent")
.finish()
}
}