Skip to content

Commit 384776b

Browse files
committed
feat: id
1 parent 93644b3 commit 384776b

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,92 @@
1+
//! Validator for Signed Document ID
2+
3+
use std::time::{Duration, SystemTime};
4+
5+
use anyhow::Context;
6+
7+
use crate::{providers::CatalystSignedDocumentProvider, CatalystSignedDocument};
8+
9+
/// Signed Document `id` field validation rule
110
pub(crate) struct IdRule;
11+
12+
impl IdRule {
13+
/// Validates document `id` field on the timestamps:
14+
/// 1. If `provider.future_threshold()` not `None`, document `id` cannot be too far in
15+
/// the future (`future_threshold` arg) from `SystemTime::now()` based on the
16+
/// provide threshold
17+
/// 2. If `provider.future_threshold()` not `None`, document `id` cannot be too far
18+
/// behind (`past_threshold` arg) from `SystemTime::now()` based on the provide
19+
/// threshold
20+
pub(crate) fn check<Provider>(
21+
self,
22+
doc: &CatalystSignedDocument,
23+
provider: &Provider,
24+
) -> anyhow::Result<bool>
25+
where
26+
Provider: CatalystSignedDocumentProvider,
27+
{
28+
let Ok(id) = doc.doc_id() else {
29+
doc.report().missing_field(
30+
"id",
31+
"Cannot get the document field during the field validation",
32+
);
33+
return Ok(false);
34+
};
35+
36+
let mut is_valid = true;
37+
38+
let (id_time_secs, id_time_nanos) = id
39+
.uuid()
40+
.get_timestamp()
41+
.ok_or(anyhow::anyhow!("Document id field must be a UUIDv7"))?
42+
.to_unix();
43+
44+
let Some(id_time) =
45+
SystemTime::UNIX_EPOCH.checked_add(Duration::new(id_time_secs, id_time_nanos))
46+
else {
47+
doc.report().invalid_value(
48+
"id",
49+
&id.to_string(),
50+
"Must a valid duration since `UNIX_EPOCH`",
51+
"Cannot instantiate a valid `SystemTime` value from the provided `id` field timestamp.",
52+
);
53+
return Ok(false);
54+
};
55+
56+
let now = SystemTime::now();
57+
58+
if let Ok(id_age) = id_time.duration_since(now) {
59+
// `now` is earlier than `id_time`
60+
if let Some(future_threshold) = provider.future_threshold() {
61+
if id_age > future_threshold {
62+
doc.report().invalid_value(
63+
"id",
64+
&id.to_string(),
65+
"id < now + future_threshold",
66+
&format!("Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now:?}"),
67+
);
68+
is_valid = false;
69+
}
70+
}
71+
} else {
72+
// `id_time` is earlier than `now`
73+
let id_age = now
74+
.duration_since(id_time)
75+
.context("BUG! `id_time` must be earlier than `now` at this place")?;
76+
77+
if let Some(past_threshold) = provider.past_threshold() {
78+
if id_age > past_threshold {
79+
doc.report().invalid_value(
80+
"id",
81+
&id.to_string(),
82+
"id > now - past_threshold",
83+
&format!("Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:?}",),
84+
);
85+
is_valid = false;
86+
}
87+
}
88+
}
89+
90+
Ok(is_valid)
91+
}
92+
}

rust/signed_doc/src/validator/ver.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,27 @@
22
33
use crate::CatalystSignedDocument;
44

5+
/// Signed Document `ver` field validation rule
56
pub(crate) struct VerRule;
67

78
impl VerRule {
9+
/// Validates document `ver` field on the timestamps:
10+
/// 1. document `ver` cannot be smaller than document `id` field
811
pub(crate) fn check(
912
&self,
1013
doc: &CatalystSignedDocument,
1114
) -> anyhow::Result<bool> {
1215
let Ok(id) = doc.doc_id() else {
1316
doc.report().missing_field(
1417
"id",
15-
"Can't get a document id during the validation process",
18+
"Cannot get the document field during the field validation",
1619
);
1720
return Ok(false);
1821
};
19-
2022
let Ok(ver) = doc.doc_ver() else {
2123
doc.report().missing_field(
2224
"ver",
23-
"Can't get a document ver during the validation process",
25+
"Cannot get the document field during the field validation",
2426
);
2527
return Ok(false);
2628
};
@@ -32,9 +34,9 @@ impl VerRule {
3234
"ver < id",
3335
&format!("Document Version {ver} cannot be smaller than Document ID {id}"),
3436
);
35-
Ok(false)
36-
} else {
37-
Ok(true)
37+
return Ok(false);
3838
}
39+
40+
Ok(true)
3941
}
4042
}

0 commit comments

Comments
 (0)