11//! Catalyst Signed Documents validation
22
3+ #![ allow( dead_code) ]
4+
35pub ( crate ) mod rules;
46pub ( crate ) mod utils;
57
6- use futures:: future:: BoxFuture ;
8+ use std:: { collections:: HashMap , sync:: LazyLock } ;
9+
10+ use catalyst_types:: uuid:: Uuid ;
11+ use rules:: { ContentEncodingRule , ContentTypeRule , Rules } ;
712
813use crate :: {
9- doc_types:: validation_rules, providers:: CatalystSignedDocumentProvider , CatalystSignedDocument ,
14+ doc_types:: { COMMENT_DOCUMENT_UUID_TYPE , PROPOSAL_DOCUMENT_UUID_TYPE } ,
15+ providers:: CatalystSignedDocumentProvider ,
16+ CatalystSignedDocument , ContentEncoding , ContentType ,
1017} ;
1118
12- /// Trait for defining a single validation rule.
13- pub ( crate ) trait ValidationRule < Provider >
14- where Provider : ' static + CatalystSignedDocumentProvider
15- {
16- /// Perform a validation rule, collecting a problem report
17- ///
18- /// # Errors
19- /// Returns an error if `provider` return an error.
20- fn check < ' a > (
21- & ' a self , doc : & ' a CatalystSignedDocument , provider : & ' a Provider ,
22- ) -> BoxFuture < ' a , anyhow:: Result < bool > > ;
19+ /// A table representing a full set or validation rules per document id.
20+ static DOCUMENT_RULES : LazyLock < HashMap < Uuid , Rules > > = LazyLock :: new ( document_rules_init) ;
21+
22+ /// `DOCUMENT_RULES` initialization function
23+ fn document_rules_init ( ) -> HashMap < Uuid , Rules > {
24+ let mut document_rules_map = HashMap :: new ( ) ;
25+
26+ let proposal_document_rules = Rules {
27+ content_type : ContentTypeRule {
28+ exp : ContentType :: Json ,
29+ } ,
30+ content_encoding : ContentEncodingRule {
31+ exp : ContentEncoding :: Brotli ,
32+ optional : false ,
33+ } ,
34+ } ;
35+ document_rules_map. insert ( PROPOSAL_DOCUMENT_UUID_TYPE , proposal_document_rules) ;
36+
37+ let comment_document_rules = Rules {
38+ content_type : ContentTypeRule {
39+ exp : ContentType :: Json ,
40+ } ,
41+ content_encoding : ContentEncodingRule {
42+ exp : ContentEncoding :: Brotli ,
43+ optional : false ,
44+ } ,
45+ } ;
46+ document_rules_map. insert ( COMMENT_DOCUMENT_UUID_TYPE , comment_document_rules) ;
47+
48+ document_rules_map
2349}
2450
2551/// A comprehensive validation of the `CatalystSignedDocument`,
@@ -33,32 +59,22 @@ pub async fn validate<Provider>(
3359 doc : & CatalystSignedDocument , provider : & Provider ,
3460) -> anyhow:: Result < bool >
3561where Provider : ' static + CatalystSignedDocumentProvider {
36- if doc. report ( ) . is_problematic ( ) {
62+ let Ok ( doc_type) = doc. doc_type ( ) else {
63+ doc. report ( ) . missing_field (
64+ "type" ,
65+ "Can't get a document type during the validation process" ,
66+ ) ;
3767 return Ok ( false ) ;
38- }
39-
40- let rules = validation_rules ( doc) ?;
41-
42- validate_rules ( rules, doc, provider) . await
43- }
68+ } ;
4469
45- /// Running a validation by the provided list of rules.
46- ///
47- /// # Errors
48- ///
49- /// If `provider` returns error, fails fast throwing that error.
50- async fn validate_rules < Provider > (
51- rules : Vec < Box < dyn ValidationRule < Provider > > > , doc : & CatalystSignedDocument ,
52- provider : & Provider ,
53- ) -> anyhow:: Result < bool >
54- where
55- Provider : ' static + CatalystSignedDocumentProvider ,
56- {
57- let checks = rules. iter ( ) . map ( |rule| rule. check ( doc, provider) ) ;
58- for res in futures:: future:: join_all ( checks) . await {
59- if !( res?) {
60- return Ok ( false ) ;
61- }
62- }
63- Ok ( true )
70+ let Some ( rules) = DOCUMENT_RULES . get ( & doc_type. uuid ( ) ) else {
71+ doc. report ( ) . invalid_value (
72+ "`type`" ,
73+ & doc. doc_type ( ) ?. to_string ( ) ,
74+ "Must be a known document type value" ,
75+ "Unsupported document type" ,
76+ ) ;
77+ return Ok ( false ) ;
78+ } ;
79+ rules. check ( doc, provider) . await
6480}
0 commit comments