Skip to content

Commit 88394bf

Browse files
authored
check against Utc::now instead of SystemTime::now (#610)
1 parent 974e33a commit 88394bf

File tree

2 files changed

+29
-24
lines changed

2 files changed

+29
-24
lines changed

rust/signed_doc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jsonschema = "0.28.3"
2727
jsonpath-rust = "0.7.5"
2828
futures = "0.3.31"
2929
ed25519-bip32 = "0.4.1" # used by the `mk_signed_doc` cli tool
30+
chrono = "0.4.42"
3031

3132

3233
[dev-dependencies]

rust/signed_doc/src/validator/mod.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,15 @@
33
pub(crate) mod rules;
44
pub(crate) mod utils;
55

6-
use std::{
7-
collections::HashMap,
8-
fmt,
9-
sync::LazyLock,
10-
time::{Duration, SystemTime},
11-
};
6+
use std::{collections::HashMap, fmt, ops::Neg, sync::LazyLock};
127

138
use anyhow::Context;
149
use catalyst_types::{
1510
catalyst_id::{role_index::RoleId, CatalystId},
1611
problem_report::ProblemReport,
1712
uuid::{Uuid, UuidV4},
1813
};
14+
use chrono::{DateTime, Utc};
1915
use coset::{CoseSign, CoseSignature};
2016
use rules::{
2117
ContentEncodingRule, ContentRule, ContentSchema, ContentTypeRule, ParametersRule, RefRule,
@@ -229,46 +225,45 @@ where
229225
.ok_or(anyhow::anyhow!("Document ver field must be a UUIDv7"))?
230226
.to_unix();
231227

232-
let Some(ver_time) =
233-
SystemTime::UNIX_EPOCH.checked_add(Duration::new(ver_time_secs, ver_time_nanos))
228+
let Some(ver_time) = i64::try_from(ver_time_secs)
229+
.ok()
230+
.and_then(|ver_time_secs| DateTime::from_timestamp(ver_time_secs, ver_time_nanos))
234231
else {
235232
doc.report().invalid_value(
236233
"ver",
237234
&ver.to_string(),
238-
"Must a valid duration since `UNIX_EPOCH`",
239-
"Cannot instantiate a valid `SystemTime` value from the provided `ver` field timestamp.",
235+
"Must a valid UTC date time since `UNIX_EPOCH`",
236+
"Cannot instantiate a valid `DateTime<Utc>` value from the provided `ver` field timestamp.",
240237
);
241238
return Ok(false);
242239
};
243240

244-
let now = SystemTime::now();
241+
let now = Utc::now();
242+
let time_delta = ver_time.signed_duration_since(now);
245243

246-
if let Ok(version_age) = ver_time.duration_since(now) {
244+
if let Ok(version_age) = time_delta.to_std() {
247245
// `now` is earlier than `ver_time`
248246
if let Some(future_threshold) = provider.future_threshold() {
249247
if version_age > future_threshold {
250248
doc.report().invalid_value(
251249
"ver",
252250
&ver.to_string(),
253251
"ver < now + future_threshold",
254-
&format!("Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now:?}"),
252+
&format!("Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now}"),
255253
);
256254
is_valid = false;
257255
}
258256
}
259257
} else {
260-
// `ver_time` is earlier than `now`
261-
let version_age = now
262-
.duration_since(ver_time)
263-
.context("BUG! `ver_time` must be earlier than `now` at this place")?;
258+
let version_age = time_delta.neg().to_std().context("BUG! Cannot fail, this condition branch already means that 'time_delta' is negative, so negating it makes it positive.")?;
264259

265260
if let Some(past_threshold) = provider.past_threshold() {
266261
if version_age > past_threshold {
267262
doc.report().invalid_value(
268263
"ver",
269264
&ver.to_string(),
270265
"ver > now - past_threshold",
271-
&format!("Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:?}",),
266+
&format!("Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now}",),
272267
);
273268
is_valid = false;
274269
}
@@ -368,8 +363,7 @@ where
368363

369364
#[cfg(test)]
370365
mod tests {
371-
use std::time::SystemTime;
372-
366+
use chrono::Utc;
373367
use uuid::{Timestamp, Uuid};
374368

375369
use crate::{
@@ -381,10 +375,8 @@ mod tests {
381375
#[test]
382376
fn document_id_and_ver_test() {
383377
let provider = TestCatalystSignedDocumentProvider::default();
384-
let now = SystemTime::now()
385-
.duration_since(SystemTime::UNIX_EPOCH)
386-
.unwrap()
387-
.as_secs();
378+
379+
let now: u64 = Utc::now().timestamp().try_into().unwrap();
388380

389381
let uuid_v7 = UuidV7::new();
390382
let doc = Builder::new()
@@ -398,6 +390,18 @@ mod tests {
398390
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
399391
assert!(is_valid);
400392

393+
let uuid_v7 = Uuid::new_v7(Timestamp::from_unix_time(now, 0, 0, 0));
394+
let doc = Builder::new()
395+
.with_json_metadata(serde_json::json!({
396+
"id": uuid_v7.to_string(),
397+
"ver": uuid_v7.to_string()
398+
}))
399+
.unwrap()
400+
.build();
401+
402+
let is_valid = validate_id_and_ver(&doc, &provider).unwrap();
403+
assert!(is_valid);
404+
401405
let ver = Uuid::new_v7(Timestamp::from_unix_time(now - 1, 0, 0, 0));
402406
let id = Uuid::new_v7(Timestamp::from_unix_time(now + 1, 0, 0, 0));
403407
assert!(ver < id);

0 commit comments

Comments
 (0)