use credo::ScopeID;
use credo::{ClaimBody, CredentialSource, Scope};
use jmbl::Input;
use litl::{impl_debug_as_litl, impl_nested_tagged_data_serde, NestedTaggedData};
use ridl::signing::SignerID;
use caro::ObjectID;
use super::Jazz;
use crate::{conventions::INCLUDE_LOG_STR, team::Team, ManagedJMBL};
#[derive(Clone)]
pub struct Doc {
pub scope: Scope,
pub managed_jmbl: ManagedJMBL,
}
impl Doc {
pub fn id(&self) -> DocID {
DocID(self.scope.id())
}
pub async fn get_author_of_log(&self, log_id: ObjectID) -> Option<SignerID> {
let expected_val = litl::to_val(log_id).unwrap();
self.scope
.current_state_as_of(ti64::now())
.valid_claims
.iter()
.find_map(|(_, (claim, _))| match &claim.body {
ClaimBody::Statement { path, value }
if path == INCLUDE_LOG_STR && value == &expected_val =>
{
Some(claim.by)
}
_ => None,
})
}
}
impl Jazz {
pub async fn create_document<I: Into<Input>>(
&self,
team: &Team,
input: I,
) -> Doc {
let credential_source = {(*self.0).borrow().main_credential_source.clone_ref()};
self.create_document_with_credential_source(
team,
input,
credential_source,
)
.await
}
pub async fn create_document_with_credential_source<I: Into<Input>>(
&self,
team: &Team,
input: I,
credential_source: Box<dyn CredentialSource>,
) -> Doc {
let credo = self.credo();
let recipient = team
.scope
.credential_for(&ClaimBody::InheritFrom {
parent: team.scope.id(),
})
.await
.expect("Expected credentials for creating documents");
let credential_source_id = credential_source.id_hash();
let doc_scope = credo
.create_scope(
recipient,
vec![],
Some(team.scope.id()),
credential_source,
)
.await;
let background = { self.0.borrow().background.clone() };
let managed_jmbl =
ManagedJMBL::create(doc_scope.clone(), input, self.content(), credo, background).await;
let doc = Doc {
scope: doc_scope,
managed_jmbl,
};
self.0
.borrow_mut()
.docs
.insert((credential_source_id, doc.id()), doc.clone());
doc
}
pub async fn load_document(&self, doc_id: DocID) -> Doc {
let credential_source = {(*self.0).borrow().main_credential_source.clone_ref()};
self.load_document_with_credential_source(
doc_id,
credential_source,
)
.await
}
pub async fn load_document_with_credential_source(
&self,
doc_id: DocID,
credential_source: Box<dyn CredentialSource>,
) -> Doc {
let existing = {self
.0
.borrow()
.docs
.get(&(credential_source.id_hash(), doc_id))
.cloned()};
match existing {
Some(doc) => doc,
None => {
let credential_source_id = credential_source.id_hash();
let doc_scope = self.credo().get_scope(&doc_id.0, credential_source);
let (managed_jmbl, loaded) = ManagedJMBL::load(
doc_scope.clone(),
self.content(),
self.0.borrow().background.clone(),
);
let doc = Doc {
scope: doc_scope,
managed_jmbl,
};
self.0
.borrow_mut()
.docs
.insert((credential_source_id, doc_id), doc.clone());
loaded.await.unwrap();
doc
}
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct DocID(pub ScopeID);
impl_nested_tagged_data_serde!(DocID);
impl_debug_as_litl!(DocID);
impl NestedTaggedData for DocID {
const TAG: &'static str = "doc";
type Inner = ScopeID;
fn as_inner(&self) -> &Self::Inner {
&self.0
}
fn from_inner(inner: Self::Inner) -> Self
where
Self: Sized,
{
DocID(inner)
}
}