use chrono::Utc;
use vti_common::error::AppError;
use vti_common::store::KeyspaceHandle;
use super::{SchemaEntry, SchemaKind, schema_exists, store_schema};
pub const DEFAULT_ISSUES_TYPES: &[(&str, &str)] = &[
("MembershipCredential", "MembershipCredential"),
("EndorsementCredential", "EndorsementCredential"),
("InvitationCredential", "InvitationCredential"),
];
const SEED_AUTHOR: &str = "did:vtc:system";
pub async fn seed_default_issues(schemas_ks: &KeyspaceHandle) -> Result<(), AppError> {
let now = Utc::now();
for (type_uri, dtg_type) in DEFAULT_ISSUES_TYPES {
if schema_exists(schemas_ks, type_uri).await? {
continue;
}
store_schema(
schemas_ks,
&SchemaEntry {
type_uri: (*type_uri).to_string(),
dtg_type: Some((*dtg_type).to_string()),
credential_schema: None,
kind: SchemaKind::Issues,
description: Some("Built-in catalog type (seeded default)".to_string()),
created_at: now,
created_by_did: SEED_AUTHOR.to_string(),
},
)
.await?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::super::{SchemaEntry, SchemaKind, get_schema, is_issues_registered, store_schema};
use super::*;
use vti_common::config::StoreConfig;
use vti_common::store::Store;
async fn ks() -> (tempfile::TempDir, Store, KeyspaceHandle) {
let dir = tempfile::tempdir().unwrap();
let store = Store::open(&StoreConfig {
data_dir: dir.path().to_path_buf(),
})
.unwrap();
let ks = store.keyspace("schemas").unwrap();
(dir, store, ks)
}
#[tokio::test]
async fn seeds_the_catalog_issues_types() {
let (_d, _s, ks) = ks().await;
seed_default_issues(&ks).await.unwrap();
for (type_uri, _) in DEFAULT_ISSUES_TYPES {
assert!(
is_issues_registered(&ks, type_uri).await.unwrap(),
"{type_uri} must be seeded as an Issues type"
);
}
}
#[tokio::test]
async fn is_idempotent_and_preserves_operator_edits() {
let (_d, _s, ks) = ks().await;
let custom = SchemaEntry {
type_uri: "MembershipCredential".into(),
dtg_type: Some("MembershipCredential".into()),
credential_schema: Some(serde_json::json!({ "type": "object" })),
kind: SchemaKind::Issues,
description: Some("operator-tuned".into()),
created_at: Utc::now(),
created_by_did: "did:key:zAdmin".into(),
};
store_schema(&ks, &custom).await.unwrap();
seed_default_issues(&ks).await.unwrap();
seed_default_issues(&ks).await.unwrap();
let got = get_schema(&ks, "MembershipCredential")
.await
.unwrap()
.unwrap();
assert_eq!(got, custom, "seeding must not overwrite an existing entry");
assert!(
is_issues_registered(&ks, "InvitationCredential")
.await
.unwrap()
);
}
}