Skip to content

Commit 17ac954

Browse files
committed
finalize
1 parent 384776b commit 17ac954

File tree

4 files changed

+36
-120
lines changed

4 files changed

+36
-120
lines changed

rust/signed_doc/src/validator/id.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ impl IdRule {
1717
/// 2. If `provider.future_threshold()` not `None`, document `id` cannot be too far
1818
/// behind (`past_threshold` arg) from `SystemTime::now()` based on the provide
1919
/// threshold
20-
pub(crate) fn check<Provider>(
21-
self,
20+
#[allow(clippy::unused_async)]
21+
pub(crate) async fn check<Provider>(
22+
&self,
2223
doc: &CatalystSignedDocument,
2324
provider: &Provider,
2425
) -> anyhow::Result<bool>
@@ -38,7 +39,7 @@ impl IdRule {
3839
let (id_time_secs, id_time_nanos) = id
3940
.uuid()
4041
.get_timestamp()
41-
.ok_or(anyhow::anyhow!("Document id field must be a UUIDv7"))?
42+
.ok_or(anyhow::anyhow!("Document `id` field must be a UUIDv7"))?
4243
.to_unix();
4344

4445
let Some(id_time) =

rust/signed_doc/src/validator/mod.rs

Lines changed: 18 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ pub(crate) mod ver;
99
use std::{
1010
collections::HashMap,
1111
sync::{Arc, LazyLock},
12-
time::{Duration, SystemTime},
1312
};
1413

1514
use anyhow::Context;
@@ -199,10 +198,6 @@ where
199198
return Ok(false);
200199
};
201200

202-
if !validate_id_and_ver(doc, provider)? {
203-
return Ok(false);
204-
}
205-
206201
let Some(rules) = DOCUMENT_RULES.get(doc_type) else {
207202
doc.report().invalid_value(
208203
"`type`",
@@ -215,106 +210,6 @@ where
215210
rules.check(doc, provider).await
216211
}
217212

218-
/// Validates document `id` and `ver` fields on the timestamps:
219-
/// 1. document `ver` cannot be smaller than document id field
220-
/// 2. If `provider.future_threshold()` not `None`, document `id` cannot be too far in the
221-
/// future (`future_threshold` arg) from `SystemTime::now()` based on the provide
222-
/// threshold
223-
/// 3. If `provider.future_threshold()` not `None`, document `id` cannot be too far behind
224-
/// (`past_threshold` arg) from `SystemTime::now()` based on the provide threshold
225-
fn validate_id_and_ver<Provider>(
226-
doc: &CatalystSignedDocument,
227-
provider: &Provider,
228-
) -> anyhow::Result<bool>
229-
where
230-
Provider: CatalystSignedDocumentProvider,
231-
{
232-
let id = doc.doc_id().ok();
233-
let ver = doc.doc_ver().ok();
234-
if id.is_none() {
235-
doc.report().missing_field(
236-
"id",
237-
"Can't get a document id during the validation process",
238-
);
239-
}
240-
if ver.is_none() {
241-
doc.report().missing_field(
242-
"ver",
243-
"Can't get a document ver during the validation process",
244-
);
245-
}
246-
match (id, ver) {
247-
(Some(id), Some(ver)) => {
248-
let mut is_valid = true;
249-
if ver < id {
250-
doc.report().invalid_value(
251-
"ver",
252-
&ver.to_string(),
253-
"ver < id",
254-
&format!("Document Version {ver} cannot be smaller than Document ID {id}"),
255-
);
256-
is_valid = false;
257-
}
258-
259-
let (ver_time_secs, ver_time_nanos) = ver
260-
.uuid()
261-
.get_timestamp()
262-
.ok_or(anyhow::anyhow!("Document ver field must be a UUIDv7"))?
263-
.to_unix();
264-
265-
let Some(ver_time) =
266-
SystemTime::UNIX_EPOCH.checked_add(Duration::new(ver_time_secs, ver_time_nanos))
267-
else {
268-
doc.report().invalid_value(
269-
"ver",
270-
&ver.to_string(),
271-
"Must a valid duration since `UNIX_EPOCH`",
272-
"Cannot instantiate a valid `SystemTime` value from the provided `ver` field timestamp.",
273-
);
274-
return Ok(false);
275-
};
276-
277-
let now = SystemTime::now();
278-
279-
if let Ok(version_age) = ver_time.duration_since(now) {
280-
// `now` is earlier than `ver_time`
281-
if let Some(future_threshold) = provider.future_threshold() {
282-
if version_age > future_threshold {
283-
doc.report().invalid_value(
284-
"ver",
285-
&ver.to_string(),
286-
"ver < now + future_threshold",
287-
&format!("Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now:?}"),
288-
);
289-
is_valid = false;
290-
}
291-
}
292-
} else {
293-
// `ver_time` is earlier than `now`
294-
let version_age = now
295-
.duration_since(ver_time)
296-
.context("BUG! `ver_time` must be earlier than `now` at this place")?;
297-
298-
if let Some(past_threshold) = provider.past_threshold() {
299-
if version_age > past_threshold {
300-
doc.report().invalid_value(
301-
"ver",
302-
&ver.to_string(),
303-
"ver > now - past_threshold",
304-
&format!("Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:?}",),
305-
);
306-
is_valid = false;
307-
}
308-
}
309-
}
310-
311-
Ok(is_valid)
312-
},
313-
314-
_ => Ok(false),
315-
}
316-
}
317-
318213
/// Verify document signatures.
319214
/// Return true if all signatures are valid, otherwise return false.
320215
///
@@ -401,12 +296,12 @@ mod tests {
401296
builder::tests::Builder,
402297
metadata::SupportedField,
403298
providers::{tests::TestCatalystSignedDocumentProvider, CatalystSignedDocumentProvider},
404-
validator::{document_rules_init, validate_id_and_ver},
299+
validator::{document_rules_init, id::IdRule, ver::VerRule},
405300
UuidV7,
406301
};
407302

408-
#[test]
409-
fn document_id_and_ver_test() {
303+
#[tokio::test]
304+
async fn document_id_and_ver_test() {
410305
let provider = TestCatalystSignedDocumentProvider::default();
411306
let now = SystemTime::now()
412307
.duration_since(SystemTime::UNIX_EPOCH)
@@ -419,8 +314,9 @@ mod tests {
419314
.with_metadata_field(SupportedField::Ver(uuid_v7))
420315
.build();
421316

422-
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
423-
assert!(is_valid);
317+
let is_id_valid = IdRule.check(&doc, &provider).await.unwrap();
318+
let is_ver_valid = VerRule.check(&doc).await.unwrap();
319+
assert!(is_id_valid && is_ver_valid);
424320

425321
let ver = Uuid::new_v7(Timestamp::from_unix_time(now - 1, 0, 0, 0))
426322
.try_into()
@@ -434,8 +330,10 @@ mod tests {
434330
.with_metadata_field(SupportedField::Ver(ver))
435331
.build();
436332

437-
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
438-
assert!(!is_valid);
333+
let is_id_valid = IdRule.check(&doc, &provider).await.unwrap();
334+
let is_ver_valid = VerRule.check(&doc).await.unwrap();
335+
assert!(is_id_valid);
336+
assert!(!is_ver_valid);
439337

440338
let to_far_in_past = Uuid::new_v7(Timestamp::from_unix_time(
441339
now - provider.past_threshold().unwrap().as_secs() - 1,
@@ -450,8 +348,10 @@ mod tests {
450348
.with_metadata_field(SupportedField::Ver(to_far_in_past))
451349
.build();
452350

453-
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
454-
assert!(!is_valid);
351+
let is_id_valid = IdRule.check(&doc, &provider).await.unwrap();
352+
let is_ver_valid = VerRule.check(&doc).await.unwrap();
353+
assert!(!is_id_valid);
354+
assert!(is_ver_valid);
455355

456356
let to_far_in_future = Uuid::new_v7(Timestamp::from_unix_time(
457357
now + provider.future_threshold().unwrap().as_secs() + 1,
@@ -466,8 +366,10 @@ mod tests {
466366
.with_metadata_field(SupportedField::Ver(to_far_in_future))
467367
.build();
468368

469-
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
470-
assert!(!is_valid);
369+
let is_id_valid = IdRule.check(&doc, &provider).await.unwrap();
370+
let is_ver_valid = VerRule.check(&doc).await.unwrap();
371+
assert!(!is_id_valid);
372+
assert!(is_ver_valid);
471373
}
472374

473375
#[test]

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ impl Rules {
6262
Provider: CatalystSignedDocumentProvider,
6363
{
6464
let rules = [
65+
self.id
66+
.as_ref()
67+
.map_or_else(|| pass().boxed(), |rule| rule.check(doc, provider).boxed()),
68+
self.ver
69+
.as_ref()
70+
.map_or_else(|| pass().boxed(), |rule| rule.check(doc).boxed()),
6571
self.content_type.check(doc).boxed(),
6672
self.content_encoding.check(doc).boxed(),
6773
self.content.check(doc, provider).boxed(),
@@ -81,3 +87,9 @@ impl Rules {
8187
Ok(res)
8288
}
8389
}
90+
91+
/// An async no-op function to pass the rule validation.
92+
#[allow(clippy::unused_async)]
93+
pub async fn pass() -> anyhow::Result<bool> {
94+
Ok(true)
95+
}

rust/signed_doc/src/validator/ver.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ pub(crate) struct VerRule;
88
impl VerRule {
99
/// Validates document `ver` field on the timestamps:
1010
/// 1. document `ver` cannot be smaller than document `id` field
11-
pub(crate) fn check(
11+
#[allow(clippy::unused_async)]
12+
pub(crate) async fn check(
1213
&self,
1314
doc: &CatalystSignedDocument,
1415
) -> anyhow::Result<bool> {

0 commit comments

Comments
 (0)