Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions rust/catalyst-signed-doc-macro/src/types_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub(crate) fn catalyst_signed_documents_types_consts_impl() -> anyhow::Result<To

let mut consts_definitions = Vec::new();
for (doc_name, doc_spec) in spec.docs {
if doc_spec.draft {
continue;
}
let const_type_name_ident = doc_name.ident();
let doc_name = doc_name.name();
let type_uuid = doc_spec.doc_type;
Expand Down
8 changes: 4 additions & 4 deletions rust/catalyst-signed-doc-spec/src/copyright.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! 'copyright' field definition

#[derive(serde::Deserialize)]
pub struct Copyright {
pub versions: Vec<Version>,
pub(crate) struct Copyright {
pub(crate) versions: Vec<Version>,
}

#[derive(serde::Deserialize)]
pub struct Version {
pub version: String,
pub(crate) struct Version {
pub(crate) version: String,
}
7 changes: 5 additions & 2 deletions rust/catalyst-signed-doc-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ pub mod doc_types;
pub mod headers;
pub mod is_required;
pub mod metadata;
pub mod payload;

use std::{collections::HashMap, fmt::Display};

use build_info as build_info_lib;

use crate::{copyright::Copyright, headers::Headers, metadata::Metadata};
use crate::{copyright::Copyright, headers::Headers, metadata::Metadata, payload::Payload};

build_info_lib::build_info!(pub(crate) fn build_info);

/// Catalyst Signed Document spec representation struct
#[derive(serde::Deserialize)]
pub struct CatalystSignedDocSpec {
pub docs: HashMap<DocumentName, DocSpec>,
pub copyright: Copyright,
copyright: Copyright,
}

// A thin wrapper over the string document name values
Expand Down Expand Up @@ -60,10 +61,12 @@ impl DocumentName {
/// Specific document type definition
#[derive(serde::Deserialize)]
pub struct DocSpec {
pub draft: bool,
#[serde(rename = "type")]
pub doc_type: String,
pub headers: Headers,
pub metadata: Metadata,
pub payload: Payload,
}

impl CatalystSignedDocSpec {
Expand Down
2 changes: 2 additions & 0 deletions rust/catalyst-signed-doc-spec/src/metadata/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! `metadata` field definition

pub mod doc_ref;
pub mod template;

/// Document's metadata fields definition
#[derive(serde::Deserialize)]
#[allow(clippy::missing_docs_in_private_items)]
pub struct Metadata {
pub template: template::Template,
#[serde(rename = "ref")]
pub doc_ref: doc_ref::Ref,
}
13 changes: 13 additions & 0 deletions rust/catalyst-signed-doc-spec/src/metadata/template.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! `signed_doc.json` "template" field JSON definition

use crate::{is_required::IsRequired, DocumentName};

/// `signed_doc.json` "template" field JSON object
#[derive(serde::Deserialize)]
#[allow(clippy::missing_docs_in_private_items, dead_code)]
pub struct Template {
pub required: IsRequired,
#[serde(rename = "type")]
pub doc_type: Option<DocumentName>,
pub multiple: Option<bool>,
}
9 changes: 9 additions & 0 deletions rust/catalyst-signed-doc-spec/src/payload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! `signed_doc.json` "payload" field JSON definition

/// `signed_doc.json` "payload" field JSON object
#[derive(serde::Deserialize)]
#[allow(clippy::missing_docs_in_private_items)]
pub struct Payload {
pub nil: bool,
pub schema: Option<serde_json::Value>,
}
21 changes: 21 additions & 0 deletions rust/signed_doc/src/validator/rules/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::fmt::Debug;

use catalyst_signed_doc_spec::payload::Payload;
use minicbor::Encode;

use crate::{
Expand Down Expand Up @@ -39,6 +40,26 @@ pub(crate) enum ContentRule {
}

impl ContentRule {
/// Generating `ContentRule` from specs
pub(crate) fn new(spec: &Payload) -> anyhow::Result<Self> {
if spec.nil {
anyhow::ensure!(
spec.schema.is_none(),
"'schema' field could not been specified when 'nil' is 'true' for 'payload' definition"
);
return Ok(Self::Nil);
}

if let Some(schema) = &spec.schema {
let schema_str = schema.to_string();
Ok(Self::StaticSchema(ContentSchema::Json(
json_schema::JsonSchema::try_from(&serde_json::from_str(&schema_str)?)?,
)))
} else {
Ok(Self::NotNil)
}
}

/// Field validation rule
#[allow(clippy::unused_async)]
pub(crate) async fn check(
Expand Down
8 changes: 6 additions & 2 deletions rust/signed_doc/src/validator/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,21 @@ impl Rules {

let mut doc_rules = Vec::new();
for doc_spec in spec.docs.values() {
if doc_spec.draft {
continue;
}

let rules = Self {
id: IdRule,
ver: VerRule,
content_type: ContentTypeRule::new(&doc_spec.headers.content_type)?,
content_encoding: ContentEncodingRule::new(&doc_spec.headers.content_encoding)?,
template: TemplateRule::NotSpecified,
template: TemplateRule::new(&spec.docs, &doc_spec.metadata.template)?,
parameters: ParametersRule::NotSpecified,
doc_ref: RefRule::new(&spec.docs, &doc_spec.metadata.doc_ref)?,
reply: ReplyRule::NotSpecified,
section: SectionRule::NotSpecified,
content: ContentRule::Nil,
content: ContentRule::new(&doc_spec.payload)?,
kid: SignatureKidRule { exp: &[] },
signature: SignatureRule { mutlisig: false },
original_author: OriginalAuthorRule,
Expand Down
39 changes: 39 additions & 0 deletions rust/signed_doc/src/validator/rules/template.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//! `template` rule type impl.

use std::collections::HashMap;

use catalyst_signed_doc_spec::{
is_required::IsRequired, metadata::template::Template, DocSpec, DocumentName,
};

use crate::{
providers::CatalystSignedDocumentProvider,
validator::{
Expand All @@ -22,6 +28,39 @@ pub(crate) enum TemplateRule {
}

impl TemplateRule {
/// Generating `TemplateRule` from specs
pub(crate) fn new(
docs: &HashMap<DocumentName, DocSpec>,
spec: &Template,
) -> anyhow::Result<Self> {
if let IsRequired::Excluded = spec.required {
anyhow::ensure!(
spec.doc_type.is_none() && spec.multiple.is_none(),
"'type' and 'multiple' fields could not been specified when 'required' is 'excluded' for 'template' metadata definition"
);
return Ok(Self::NotSpecified);
}

anyhow::ensure!(
spec.multiple.is_some_and(|v| !v),
"'multiple' must be `false` for 'template' metadata definition"
);
anyhow::ensure!(
spec.required != IsRequired::Optional,
"'required' field cannot been 'optional' for 'template' metadata definition"
);

let doc_name = spec.doc_type.as_ref().ok_or(anyhow::anyhow!(
"'type' field should exists for the required 'template' metadata definition"
))?;
let docs_spec = docs.get(doc_name).ok_or(anyhow::anyhow!(
"cannot find a document definition {doc_name}"
))?;
let allowed_type = docs_spec.doc_type.as_str().parse()?;

Ok(Self::Specified { allowed_type })
}

/// Field validation rule
pub(crate) async fn check<Provider>(
&self,
Expand Down
Loading