11//! Validator for Signed Document Version
22
3- use crate :: CatalystSignedDocument ;
3+ use crate :: {
4+ providers:: CatalystSignedDocumentProvider , CatalystSignedDocument , DocLocator , DocumentRef ,
5+ } ;
46
57/// Signed Document `ver` field validation rule
68pub ( crate ) struct VerRule ;
@@ -9,10 +11,14 @@ impl VerRule {
911 /// Validates document `ver` field on the timestamps:
1012 /// 1. document `ver` cannot be smaller than document `id` field
1113 #[ allow( clippy:: unused_async) ]
12- pub ( crate ) async fn check (
14+ pub ( crate ) async fn check < Provider > (
1315 & self ,
1416 doc : & CatalystSignedDocument ,
15- ) -> anyhow:: Result < bool > {
17+ provider : & Provider ,
18+ ) -> anyhow:: Result < bool >
19+ where
20+ Provider : CatalystSignedDocumentProvider ,
21+ {
1622 let Ok ( id) = doc. doc_id ( ) else {
1723 doc. report ( ) . missing_field (
1824 "id" ,
@@ -28,17 +34,30 @@ impl VerRule {
2834 return Ok ( false ) ;
2935 } ;
3036
37+ let mut is_valid = true ;
38+
3139 if ver < id {
3240 doc. report ( ) . invalid_value (
3341 "ver" ,
3442 & ver. to_string ( ) ,
3543 "ver < id" ,
3644 & format ! ( "Document Version {ver} cannot be smaller than Document ID {id}" ) ,
3745 ) ;
38- return Ok ( false ) ;
46+ is_valid = false ;
47+ }
48+
49+ if ver != id {
50+ let first_submited_doc = DocumentRef :: new ( id, id, DocLocator :: default ( ) ) ;
51+ if provider. try_get_doc ( & first_submited_doc) . await ?. is_none ( ) {
52+ doc. report ( ) . functional_validation (
53+ & format ! ( "`ver` and `id` are not equal, ver: {ver}, id: {id}. Document with `id` and `ver` being equal MUST exist" ) ,
54+ "Cannot get a first version document from the provider, document for which `id` and `ver` are equal." ,
55+ ) ;
56+ is_valid = false ;
57+ }
3958 }
4059
41- Ok ( true )
60+ Ok ( is_valid )
4261 }
4362}
4463
@@ -50,10 +69,13 @@ mod tests {
5069 use uuid:: { Timestamp , Uuid } ;
5170
5271 use super :: * ;
53- use crate :: { builder:: tests:: Builder , metadata:: SupportedField , UuidV7 } ;
72+ use crate :: {
73+ builder:: tests:: Builder , metadata:: SupportedField ,
74+ providers:: tests:: TestCatalystSignedDocumentProvider , UuidV7 ,
75+ } ;
5476
5577 #[ test_case(
56- || {
78+ |_ | {
5779 let uuid_v7 = UuidV7 :: new( ) ;
5880 Builder :: new( )
5981 . with_metadata_field( SupportedField :: Id ( uuid_v7) )
@@ -64,15 +86,21 @@ mod tests {
6486 "`ver` and `id` are equal"
6587 ) ]
6688 #[ test_case(
67- || {
89+ |provider | {
6890 let now = SystemTime :: now( )
6991 . duration_since( SystemTime :: UNIX_EPOCH )
7092 . unwrap( )
7193 . as_secs( ) ;
72- let ver = Uuid :: new_v7( Timestamp :: from_unix_time( now + 1 , 0 , 0 , 0 ) )
94+ let id = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
7395 . try_into( )
7496 . unwrap( ) ;
75- let id = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
97+ let first_doc = Builder :: new( )
98+ . with_metadata_field( SupportedField :: Id ( id) )
99+ . with_metadata_field( SupportedField :: Ver ( id) )
100+ . build( ) ;
101+ provider. add_document( None , & first_doc) . unwrap( ) ;
102+
103+ let ver = Uuid :: new_v7( Timestamp :: from_unix_time( now + 1 , 0 , 0 , 0 ) )
76104 . try_into( )
77105 . unwrap( ) ;
78106 Builder :: new( )
@@ -84,15 +112,41 @@ mod tests {
84112 "`ver` greater than `id` are equal"
85113 ) ]
86114 #[ test_case(
87- || {
115+ |provider| {
116+ let now = SystemTime :: now( )
117+ . duration_since( SystemTime :: UNIX_EPOCH )
118+ . unwrap( )
119+ . as_secs( ) ;
120+ let id = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
121+ . try_into( )
122+ . unwrap( ) ;
123+ let first_doc = Builder :: new( )
124+ . with_metadata_field( SupportedField :: Id ( id) )
125+ . with_metadata_field( SupportedField :: Ver ( id) )
126+ . build( ) ;
127+ provider. add_document( None , & first_doc) . unwrap( ) ;
128+
129+ let ver = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
130+ . try_into( )
131+ . unwrap( ) ;
132+ Builder :: new( )
133+ . with_metadata_field( SupportedField :: Id ( id) )
134+ . with_metadata_field( SupportedField :: Ver ( ver) )
135+ . build( )
136+ }
137+ => false ;
138+ "`ver` less than `id` are equal"
139+ ) ]
140+ #[ test_case(
141+ |_| {
88142 let now = SystemTime :: now( )
89143 . duration_since( SystemTime :: UNIX_EPOCH )
90144 . unwrap( )
91145 . as_secs( ) ;
92- let ver = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
146+ let id = Uuid :: new_v7( Timestamp :: from_unix_time( now - 1 , 0 , 0 , 0 ) )
93147 . try_into( )
94148 . unwrap( ) ;
95- let id = Uuid :: new_v7( Timestamp :: from_unix_time( now + 1 , 0 , 0 , 0 ) )
149+ let ver = Uuid :: new_v7( Timestamp :: from_unix_time( now + 1 , 0 , 0 , 0 ) )
96150 . try_into( )
97151 . unwrap( ) ;
98152 Builder :: new( )
@@ -101,10 +155,10 @@ mod tests {
101155 . build( )
102156 }
103157 => false ;
104- "`ver` less than `id` are equal "
158+ "missing first version document "
105159 ) ]
106160 #[ test_case(
107- || {
161+ |_ | {
108162 Builder :: new( )
109163 . with_metadata_field( SupportedField :: Id ( UuidV7 :: new( ) ) )
110164 . build( )
@@ -113,7 +167,7 @@ mod tests {
113167 "missing `ver` field"
114168 ) ]
115169 #[ test_case(
116- || {
170+ |_ | {
117171 Builder :: new( )
118172 . with_metadata_field( SupportedField :: Ver ( UuidV7 :: new( ) ) )
119173 . build( )
@@ -122,9 +176,12 @@ mod tests {
122176 "missing `id` field"
123177 ) ]
124178 #[ tokio:: test]
125- async fn ver_test ( doc_gen : impl FnOnce ( ) -> CatalystSignedDocument ) -> bool {
126- let doc = doc_gen ( ) ;
179+ async fn ver_test (
180+ doc_gen : impl FnOnce ( & mut TestCatalystSignedDocumentProvider ) -> CatalystSignedDocument
181+ ) -> bool {
182+ let mut provider = TestCatalystSignedDocumentProvider :: default ( ) ;
183+ let doc = doc_gen ( & mut provider) ;
127184
128- VerRule . check ( & doc) . await . unwrap ( )
185+ VerRule . check ( & doc, & provider ) . await . unwrap ( )
129186 }
130187}
0 commit comments