Skip to content

Commit 41ea811

Browse files
fix(rust/signed-doc): Update DocumentRef to require version field (#271)
* fix(rust/signed-doc): DocumentRef requires version field * fix(rust/signed-doc): WIP update test docrefs * fix(rust/signed-doc): update docrefs in tests --------- Co-authored-by: Alex Pozhylenkov <[email protected]>
1 parent abf2da4 commit 41ea811

File tree

9 files changed

+144
-102
lines changed

9 files changed

+144
-102
lines changed

rust/signed_doc/src/metadata/document_ref.rs

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,24 @@ use super::{utils::CborUuidV7, UuidV7};
1111
pub struct DocumentRef {
1212
/// Reference to the Document Id
1313
pub id: UuidV7,
14-
/// Reference to the Document Ver, if not specified the latest document is meant
15-
#[serde(skip_serializing_if = "Option::is_none")]
16-
pub ver: Option<UuidV7>,
14+
/// Reference to the Document Ver
15+
pub ver: UuidV7,
1716
}
1817

1918
impl Display for DocumentRef {
2019
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21-
if let Some(ver) = self.ver {
22-
write!(f, "id: {}, ver: {}", self.id, ver)
23-
} else {
24-
write!(f, "id: {}", self.id)
25-
}
20+
write!(f, "id: {}, ver: {}", self.id, self.ver)
2621
}
2722
}
2823

2924
impl TryFrom<DocumentRef> for Value {
3025
type Error = anyhow::Error;
3126

3227
fn try_from(value: DocumentRef) -> Result<Self, Self::Error> {
33-
if let Some(ver) = value.ver {
34-
Ok(Value::Array(vec![
35-
Value::try_from(CborUuidV7(value.id))?,
36-
Value::try_from(CborUuidV7(ver))?,
37-
]))
38-
} else {
39-
Value::try_from(CborUuidV7(value.id))
40-
}
28+
Ok(Value::Array(vec![
29+
Value::try_from(CborUuidV7(value.id))?,
30+
Value::try_from(CborUuidV7(value.ver))?,
31+
]))
4132
}
4233
}
4334

@@ -46,23 +37,19 @@ impl TryFrom<&Value> for DocumentRef {
4637

4738
#[allow(clippy::indexing_slicing)]
4839
fn try_from(val: &Value) -> anyhow::Result<DocumentRef> {
49-
if let Ok(CborUuidV7(id)) = CborUuidV7::try_from(val) {
50-
Ok(DocumentRef { id, ver: None })
51-
} else {
52-
let Some(array) = val.as_array() else {
53-
anyhow::bail!("Document Reference must be either a single UUID or an array of two");
54-
};
55-
anyhow::ensure!(
56-
array.len() == 2,
57-
"Document Reference array of two UUIDs was expected"
58-
);
59-
let CborUuidV7(id) = CborUuidV7::try_from(&array[0])?;
60-
let CborUuidV7(ver) = CborUuidV7::try_from(&array[1])?;
61-
anyhow::ensure!(
62-
ver >= id,
63-
"Document Reference Version can never be smaller than its ID"
64-
);
65-
Ok(DocumentRef { id, ver: Some(ver) })
66-
}
40+
let Some(array) = val.as_array() else {
41+
anyhow::bail!("Document Reference must be either a single UUID or an array of two");
42+
};
43+
anyhow::ensure!(
44+
array.len() == 2,
45+
"Document Reference array of two UUIDs was expected"
46+
);
47+
let CborUuidV7(id) = CborUuidV7::try_from(&array[0])?;
48+
let CborUuidV7(ver) = CborUuidV7::try_from(&array[1])?;
49+
anyhow::ensure!(
50+
ver >= id,
51+
"Document Reference Version can never be smaller than its ID"
52+
);
53+
Ok(DocumentRef { id, ver })
6754
}
6855
}

rust/signed_doc/src/validator/rules/category.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ mod tests {
7070
let mut provider = TestCatalystSignedDocumentProvider::default();
7171

7272
let valid_category_doc_id = UuidV7::new();
73+
let valid_category_doc_ver = UuidV7::new();
7374
let another_type_category_doc_id = UuidV7::new();
75+
let another_type_category_doc_ver = UuidV7::new();
7476
let missing_type_category_doc_id = UuidV7::new();
77+
let missing_type_category_doc_ver = UuidV7::new();
7578

7679
// prepare replied documents
7780
{
7881
let ref_doc = Builder::new()
7982
.with_json_metadata(serde_json::json!({
8083
"id": valid_category_doc_id.to_string(),
84+
"ver": valid_category_doc_ver.to_string(),
8185
"type": CATEGORY_DOCUMENT_UUID_TYPE.to_string()
8286
}))
8387
.unwrap()
@@ -88,6 +92,7 @@ mod tests {
8892
let ref_doc = Builder::new()
8993
.with_json_metadata(serde_json::json!({
9094
"id": another_type_category_doc_id.to_string(),
95+
"ver": another_type_category_doc_ver.to_string(),
9196
"type": UuidV4::new().to_string()
9297
}))
9398
.unwrap()
@@ -98,6 +103,7 @@ mod tests {
98103
let ref_doc = Builder::new()
99104
.with_json_metadata(serde_json::json!({
100105
"id": missing_type_category_doc_id.to_string(),
106+
"ver": missing_type_category_doc_ver.to_string(),
101107
}))
102108
.unwrap()
103109
.build();
@@ -108,7 +114,7 @@ mod tests {
108114
let rule = CategoryRule::Specified { optional: false };
109115
let doc = Builder::new()
110116
.with_json_metadata(serde_json::json!({
111-
"category_id": {"id": valid_category_doc_id.to_string() }
117+
"category_id": {"id": valid_category_doc_id.to_string(), "ver": valid_category_doc_ver }
112118
}))
113119
.unwrap()
114120
.build();
@@ -127,7 +133,7 @@ mod tests {
127133
// reference to the document with another `type` field
128134
let doc = Builder::new()
129135
.with_json_metadata(serde_json::json!({
130-
"category_id": {"id": another_type_category_doc_id.to_string() }
136+
"category_id": {"id": another_type_category_doc_id.to_string(), "ver": another_type_category_doc_ver.to_string() }
131137
}))
132138
.unwrap()
133139
.build();
@@ -136,7 +142,7 @@ mod tests {
136142
// missing `type` field in the referenced document
137143
let doc = Builder::new()
138144
.with_json_metadata(serde_json::json!({
139-
"category_id": {"id": missing_type_category_doc_id.to_string() }
145+
"category_id": {"id": missing_type_category_doc_id.to_string(), "ver": missing_type_category_doc_ver.to_string() }
140146
}))
141147
.unwrap()
142148
.build();
@@ -145,7 +151,7 @@ mod tests {
145151
// cannot find a referenced document
146152
let doc = Builder::new()
147153
.with_json_metadata(serde_json::json!({
148-
"category_id": {"id": UuidV7::new().to_string() }
154+
"category_id": {"id": UuidV7::new().to_string(), "ver": UuidV7::new().to_string() }
149155
}))
150156
.unwrap()
151157
.build();
@@ -162,8 +168,11 @@ mod tests {
162168
assert!(rule.check(&doc, &provider).await.unwrap());
163169

164170
let ref_id = UuidV7::new();
171+
let ref_ver = UuidV7::new();
165172
let doc = Builder::new()
166-
.with_json_metadata(serde_json::json!({"category_id": {"id": ref_id.to_string() } }))
173+
.with_json_metadata(serde_json::json!({
174+
"category_id": {"id": ref_id.to_string(), "ver": ref_ver.to_string(), }
175+
}))
167176
.unwrap()
168177
.build();
169178
assert!(!rule.check(&doc, &provider).await.unwrap());

rust/signed_doc/src/validator/rules/doc_ref.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,18 @@ mod tests {
9595
let exp_ref_type = UuidV4::new();
9696

9797
let valid_referenced_doc_id = UuidV7::new();
98+
let valid_referenced_doc_ver = UuidV7::new();
9899
let another_type_referenced_doc_id = UuidV7::new();
100+
let another_type_referenced_doc_ver = UuidV7::new();
99101
let missing_type_referenced_doc_id = UuidV7::new();
102+
let missing_type_referenced_doc_ver = UuidV7::new();
100103

101104
// prepare replied documents
102105
{
103106
let ref_doc = Builder::new()
104107
.with_json_metadata(serde_json::json!({
105108
"id": valid_referenced_doc_id.to_string(),
109+
"ver": valid_referenced_doc_ver.to_string(),
106110
"type": exp_ref_type.to_string()
107111
}))
108112
.unwrap()
@@ -113,6 +117,7 @@ mod tests {
113117
let ref_doc = Builder::new()
114118
.with_json_metadata(serde_json::json!({
115119
"id": another_type_referenced_doc_id.to_string(),
120+
"ver": another_type_referenced_doc_ver.to_string(),
116121
"type": UuidV4::new().to_string()
117122
}))
118123
.unwrap()
@@ -123,6 +128,7 @@ mod tests {
123128
let ref_doc = Builder::new()
124129
.with_json_metadata(serde_json::json!({
125130
"id": missing_type_referenced_doc_id.to_string(),
131+
"ver": missing_type_referenced_doc_ver.to_string(),
126132
}))
127133
.unwrap()
128134
.build();
@@ -136,7 +142,7 @@ mod tests {
136142
};
137143
let doc = Builder::new()
138144
.with_json_metadata(serde_json::json!({
139-
"ref": {"id": valid_referenced_doc_id.to_string() }
145+
"ref": {"id": valid_referenced_doc_id.to_string(), "ver": valid_referenced_doc_ver.to_string() }
140146
}))
141147
.unwrap()
142148
.build();
@@ -161,7 +167,7 @@ mod tests {
161167
// reference to the document with another `type` field
162168
let doc = Builder::new()
163169
.with_json_metadata(serde_json::json!({
164-
"ref": {"id": another_type_referenced_doc_id.to_string() }
170+
"ref": {"id": another_type_referenced_doc_id.to_string(), "ver": another_type_referenced_doc_ver.to_string() }
165171
}))
166172
.unwrap()
167173
.build();
@@ -170,7 +176,7 @@ mod tests {
170176
// missing `type` field in the referenced document
171177
let doc = Builder::new()
172178
.with_json_metadata(serde_json::json!({
173-
"ref": {"id": missing_type_referenced_doc_id.to_string() }
179+
"ref": {"id": missing_type_referenced_doc_id.to_string(), "ver": missing_type_referenced_doc_ver.to_string() }
174180
}))
175181
.unwrap()
176182
.build();
@@ -179,7 +185,7 @@ mod tests {
179185
// cannot find a referenced document
180186
let doc = Builder::new()
181187
.with_json_metadata(serde_json::json!({
182-
"ref": {"id": UuidV7::new().to_string() }
188+
"ref": {"id": UuidV7::new().to_string(), "ver": UuidV7::new().to_string() }
183189
}))
184190
.unwrap()
185191
.build();
@@ -195,8 +201,9 @@ mod tests {
195201
assert!(rule.check(&doc, &provider).await.unwrap());
196202

197203
let ref_id = UuidV7::new();
204+
let ref_ver = UuidV7::new();
198205
let doc = Builder::new()
199-
.with_json_metadata(serde_json::json!({"ref": {"id": ref_id.to_string() } }))
206+
.with_json_metadata(serde_json::json!({"ref": {"id": ref_id.to_string(), "ver": ref_ver.to_string() } }))
200207
.unwrap()
201208
.build();
202209
assert!(!rule.check(&doc, &provider).await.unwrap());

rust/signed_doc/src/validator/rules/reply.rs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,24 @@ mod tests {
104104

105105
let exp_reply_type = UuidV4::new();
106106
let common_ref_id = UuidV7::new();
107+
let common_ref_ver = UuidV7::new();
107108

108109
let valid_replied_doc_id = UuidV7::new();
110+
let valid_replied_doc_ver = UuidV7::new();
111+
let another_type_replied_doc_ver = UuidV7::new();
109112
let another_type_replied_doc_id = UuidV7::new();
113+
let missing_ref_replied_doc_ver = UuidV7::new();
110114
let missing_ref_replied_doc_id = UuidV7::new();
115+
let missing_type_replied_doc_ver = UuidV7::new();
111116
let missing_type_replied_doc_id = UuidV7::new();
112117

113118
// prepare replied documents
114119
{
115120
let ref_doc = Builder::new()
116121
.with_json_metadata(serde_json::json!({
117-
"ref": { "id": common_ref_id.to_string() },
122+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
118123
"id": valid_replied_doc_id.to_string(),
124+
"ver": valid_replied_doc_ver.to_string(),
119125
"type": exp_reply_type.to_string()
120126
}))
121127
.unwrap()
@@ -125,8 +131,9 @@ mod tests {
125131
// reply doc with other `type` field
126132
let ref_doc = Builder::new()
127133
.with_json_metadata(serde_json::json!({
128-
"ref": { "id": common_ref_id.to_string() },
134+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
129135
"id": another_type_replied_doc_id.to_string(),
136+
"ver": another_type_replied_doc_ver.to_string(),
130137
"type": UuidV4::new().to_string()
131138
}))
132139
.unwrap()
@@ -137,6 +144,7 @@ mod tests {
137144
let ref_doc = Builder::new()
138145
.with_json_metadata(serde_json::json!({
139146
"id": missing_ref_replied_doc_id.to_string(),
147+
"ver": missing_ref_replied_doc_ver.to_string(),
140148
"type": exp_reply_type.to_string()
141149
}))
142150
.unwrap()
@@ -146,8 +154,9 @@ mod tests {
146154
// missing `type` field in the referenced document
147155
let ref_doc = Builder::new()
148156
.with_json_metadata(serde_json::json!({
149-
"ref": { "id": common_ref_id.to_string() },
157+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
150158
"id": missing_type_replied_doc_id.to_string(),
159+
"ver": missing_type_replied_doc_ver.to_string(),
151160
}))
152161
.unwrap()
153162
.build();
@@ -161,8 +170,8 @@ mod tests {
161170
};
162171
let doc = Builder::new()
163172
.with_json_metadata(serde_json::json!({
164-
"ref": { "id": common_ref_id.to_string() },
165-
"reply": { "id": valid_replied_doc_id.to_string() }
173+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
174+
"reply": { "id": valid_replied_doc_id.to_string(), "ver": valid_replied_doc_ver.to_string() }
166175
}))
167176
.unwrap()
168177
.build();
@@ -183,7 +192,7 @@ mod tests {
183192
};
184193
let doc = Builder::new()
185194
.with_json_metadata(serde_json::json!({
186-
"ref": { "id": common_ref_id.to_string() },
195+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
187196
}))
188197
.unwrap()
189198
.build();
@@ -192,7 +201,7 @@ mod tests {
192201
// missing `ref` field
193202
let doc = Builder::new()
194203
.with_json_metadata(serde_json::json!({
195-
"reply": { "id": valid_replied_doc_id.to_string() }
204+
"reply": { "id": valid_replied_doc_id.to_string(), "ver": valid_replied_doc_ver.to_string() }
196205
}))
197206
.unwrap()
198207
.build();
@@ -201,8 +210,8 @@ mod tests {
201210
// reference to the document with another `type` field
202211
let doc = Builder::new()
203212
.with_json_metadata(serde_json::json!({
204-
"ref": { "id": common_ref_id.to_string() },
205-
"reply": { "id": another_type_replied_doc_id.to_string() }
213+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
214+
"reply": { "id": another_type_replied_doc_id.to_string(), "ver": another_type_replied_doc_ver.to_string() }
206215
}))
207216
.unwrap()
208217
.build();
@@ -211,8 +220,8 @@ mod tests {
211220
// missing `ref` field in the referenced document
212221
let doc = Builder::new()
213222
.with_json_metadata(serde_json::json!({
214-
"ref": { "id": common_ref_id.to_string() },
215-
"reply": { "id": missing_ref_replied_doc_id.to_string() }
223+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
224+
"reply": { "id": missing_ref_replied_doc_id.to_string(), "ver": missing_type_replied_doc_ver.to_string() }
216225
}))
217226
.unwrap()
218227
.build();
@@ -221,8 +230,8 @@ mod tests {
221230
// missing `type` field in the referenced document
222231
let doc = Builder::new()
223232
.with_json_metadata(serde_json::json!({
224-
"ref": {"id": common_ref_id.to_string() },
225-
"reply": { "id": missing_type_replied_doc_id.to_string() }
233+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
234+
"reply": { "id": missing_type_replied_doc_id.to_string(), "ver": missing_type_replied_doc_ver.to_string() }
226235
}))
227236
.unwrap()
228237
.build();
@@ -231,8 +240,8 @@ mod tests {
231240
// `ref` field does not align with the referenced document
232241
let doc = Builder::new()
233242
.with_json_metadata(serde_json::json!({
234-
"ref": { "id": UuidV7::new().to_string() },
235-
"reply": { "id": valid_replied_doc_id.to_string() }
243+
"ref": { "id": UuidV7::new().to_string(), "ver": UuidV7::new().to_string() },
244+
"reply": { "id": valid_replied_doc_id.to_string(), "ver": valid_replied_doc_ver.to_string() }
236245
}))
237246
.unwrap()
238247
.build();
@@ -241,8 +250,8 @@ mod tests {
241250
// cannot find a referenced document
242251
let doc = Builder::new()
243252
.with_json_metadata(serde_json::json!({
244-
"ref": { "id": common_ref_id.to_string() },
245-
"reply": {"id": UuidV7::new().to_string() }
253+
"ref": { "id": common_ref_id.to_string(), "ver": common_ref_ver.to_string() },
254+
"reply": {"id": UuidV7::new().to_string(), "ver": UuidV7::new().to_string() }
246255
}))
247256
.unwrap()
248257
.build();
@@ -258,8 +267,9 @@ mod tests {
258267
assert!(rule.check(&doc, &provider).await.unwrap());
259268

260269
let ref_id = UuidV7::new();
270+
let ref_ver = UuidV7::new();
261271
let doc = Builder::new()
262-
.with_json_metadata(serde_json::json!({"reply": {"id": ref_id.to_string() } }))
272+
.with_json_metadata(serde_json::json!({"reply": {"id": ref_id.to_string(), "ver": ref_ver.to_string() } }))
263273
.unwrap()
264274
.build();
265275
assert!(!rule.check(&doc, &provider).await.unwrap());

0 commit comments

Comments
 (0)