diff --git a/Cargo.lock b/Cargo.lock index 4e6c5714..05a71c85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -896,9 +896,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", diff --git a/Cargo.toml b/Cargo.toml index f1d7f075..eb77e56a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ version = "1.1.6" # Time utilities [workspace.dependencies.chrono] -version = "0.4.33" +version = "0.4.35" default-features = false features = ["serde", "clock"] diff --git a/crates/axum-utils/src/csrf.rs b/crates/axum-utils/src/csrf.rs index 698ca28a..d414aa06 100644 --- a/crates/axum-utils/src/csrf.rs +++ b/crates/axum-utils/src/csrf.rs @@ -153,8 +153,8 @@ impl CsrfExt for CookieJar { }; let token = maybe_token.map_or_else( - || CsrfToken::generate(now, rng, Duration::hours(1)), - |token| token.refresh(now, Duration::hours(1)), + || CsrfToken::generate(now, rng, Duration::try_hours(1).unwrap()), + |token| token.refresh(now, Duration::try_hours(1).unwrap()), ); let jar = self.save("csrf", &token, false); diff --git a/crates/config/src/sections/experimental.rs b/crates/config/src/sections/experimental.rs index 5c224495..594abac2 100644 --- a/crates/config/src/sections/experimental.rs +++ b/crates/config/src/sections/experimental.rs @@ -22,7 +22,7 @@ use serde_with::serde_as; use crate::ConfigurationSection; fn default_token_ttl() -> Duration { - Duration::minutes(5) + Duration::microseconds(5 * 60 * 1000 * 1000) } /// Configuration sections for experimental options diff --git a/crates/data-model/src/oauth2/authorization_grant.rs b/crates/data-model/src/oauth2/authorization_grant.rs index e7d9d459..f9bcc056 100644 --- a/crates/data-model/src/oauth2/authorization_grant.rs +++ b/crates/data-model/src/oauth2/authorization_grant.rs @@ -175,11 +175,16 @@ impl std::ops::Deref for AuthorizationGrant { } } +const DEFAULT_MAX_AGE: Duration = Duration::microseconds(3600 * 24 * 365 * 1000 * 1000); + impl AuthorizationGrant { #[must_use] pub fn max_auth_time(&self) -> DateTime { - let max_age: Option = self.max_age.map(|x| x.get().into()); - self.created_at - Duration::seconds(max_age.unwrap_or(3600 * 24 * 365)) + let max_age = self + .max_age + .and_then(|x| Duration::try_seconds(x.get().into())) + .unwrap_or(DEFAULT_MAX_AGE); + self.created_at - max_age } /// Mark the authorization grant as exchanged. diff --git a/crates/data-model/src/users.rs b/crates/data-model/src/users.rs index 30d07179..2be860ae 100644 --- a/crates/data-model/src/users.rs +++ b/crates/data-model/src/users.rs @@ -185,10 +185,10 @@ impl UserEmailVerification { pub fn samples(now: chrono::DateTime, rng: &mut impl Rng) -> Vec { let states = [ UserEmailVerificationState::AlreadyUsed { - when: now - Duration::minutes(5), + when: now - Duration::microseconds(5 * 60 * 1000 * 1000), }, UserEmailVerificationState::Expired { - when: now - Duration::hours(5), + when: now - Duration::microseconds(5 * 60 * 1000 * 1000), }, UserEmailVerificationState::Valid, ]; @@ -204,7 +204,7 @@ impl UserEmailVerification { id: Ulid::from_datetime_with_source(now.into(), &mut rng), user_email_id: email.id, code: "123456".to_owned(), - created_at: now - Duration::minutes(10), + created_at: now - Duration::microseconds(10 * 60 * 1000 * 1000), state: state.clone(), }) }) diff --git a/crates/graphql/src/mutations/oauth2_session.rs b/crates/graphql/src/mutations/oauth2_session.rs index 0e604a11..c3c7088c 100644 --- a/crates/graphql/src/mutations/oauth2_session.rs +++ b/crates/graphql/src/mutations/oauth2_session.rs @@ -179,7 +179,7 @@ impl OAuth2SessionMutations { let ttl = if permanent { None } else { - Some(Duration::minutes(5)) + Some(Duration::microseconds(5 * 60 * 1000 * 1000)) }; let access_token = repo .oauth2_access_token() diff --git a/crates/handlers/src/compat/login.rs b/crates/handlers/src/compat/login.rs index 4da7483f..2bfdf9d4 100644 --- a/crates/handlers/src/compat/login.rs +++ b/crates/handlers/src/compat/login.rs @@ -321,7 +321,7 @@ async fn token_login( session_id, .. } => { - if now > fulfilled_at + Duration::seconds(30) { + if now > fulfilled_at + Duration::microseconds(30 * 1000 * 1000) { return Err(RouteError::LoginTookTooLong); } @@ -332,7 +332,7 @@ async fn token_login( session_id, .. } => { - if now > exchanged_at + Duration::seconds(30) { + if now > exchanged_at + Duration::microseconds(30 * 1000 * 1000) { // TODO: log that session out tracing::error!( compat_sso_login.id = %login.id, @@ -706,7 +706,9 @@ mod tests { let (_device, token) = get_login_token(&state, &user).await; // Advance the clock to make the token expire. - state.clock.advance(Duration::minutes(1)); + state + .clock + .advance(Duration::microseconds(60 * 1000 * 1000)); let request = Request::post("/_matrix/client/v3/login").json(serde_json::json!({ "type": "m.login.token", diff --git a/crates/handlers/src/compat/login_sso_complete.rs b/crates/handlers/src/compat/login_sso_complete.rs index 756c7ebf..728ed073 100644 --- a/crates/handlers/src/compat/login_sso_complete.rs +++ b/crates/handlers/src/compat/login_sso_complete.rs @@ -103,7 +103,7 @@ pub async fn get( .context("Could not find compat SSO login")?; // Bail out if that login session is more than 30min old - if clock.now() > login.created_at + Duration::minutes(30) { + if clock.now() > login.created_at + Duration::microseconds(30 * 60 * 1000 * 1000) { let ctx = ErrorContext::new() .with_code("compat_sso_login_expired") .with_description("This login session expired.".to_owned()) @@ -174,7 +174,7 @@ pub async fn post( .context("Could not find compat SSO login")?; // Bail out if that login session is more than 30min old - if clock.now() > login.created_at + Duration::minutes(30) { + if clock.now() > login.created_at + Duration::microseconds(30 * 60 * 1000 * 1000) { let ctx = ErrorContext::new() .with_code("compat_sso_login_expired") .with_description("This login session expired.".to_owned()) diff --git a/crates/handlers/src/oauth2/device/authorize.rs b/crates/handlers/src/oauth2/device/authorize.rs index 1428fcf3..4cc9ed8b 100644 --- a/crates/handlers/src/oauth2/device/authorize.rs +++ b/crates/handlers/src/oauth2/device/authorize.rs @@ -124,7 +124,7 @@ pub(crate) async fn post( // XXX: Is this really how we do empty scopes? .unwrap_or(std::iter::empty::().collect()); - let expires_in = Duration::minutes(20); + let expires_in = Duration::microseconds(20 * 60 * 1000 * 1000); let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned())); let ip_address = activity_tracker.ip(); @@ -157,7 +157,7 @@ pub(crate) async fn post( verification_uri: url_builder.device_code_link(), verification_uri_complete: Some(url_builder.device_code_link_full(device_code.user_code)), expires_in, - interval: Some(Duration::seconds(5)), + interval: Some(Duration::microseconds(5 * 1000 * 1000)), }; Ok(( diff --git a/crates/handlers/src/oauth2/introspection.rs b/crates/handlers/src/oauth2/introspection.rs index 27af1875..fdf44676 100644 --- a/crates/handlers/src/oauth2/introspection.rs +++ b/crates/handlers/src/oauth2/introspection.rs @@ -550,7 +550,7 @@ mod tests { &state.clock, &mut repo, &session, - Duration::minutes(5), + Duration::microseconds(5 * 60 * 1000 * 1000), ) .await .unwrap(); @@ -633,7 +633,7 @@ mod tests { // Advance the clock to invalidate the access token let old_now = state.clock.now(); - state.clock.advance(Duration::hours(1)); + state.clock.advance(Duration::try_hours(1).unwrap()); let request = Request::post(OAuth2Introspection::PATH) .basic_auth(&introspecting_client_id, &introspecting_client_secret) @@ -808,7 +808,7 @@ mod tests { assert!(!response.active); // It shouldn't be active // Advance the clock to invalidate the access token - state.clock.advance(Duration::hours(1)); + state.clock.advance(Duration::try_hours(1).unwrap()); let request = Request::post(OAuth2Introspection::PATH) .basic_auth(&introspecting_client_id, &introspecting_client_secret) diff --git a/crates/handlers/src/oauth2/mod.rs b/crates/handlers/src/oauth2/mod.rs index 8f220c6e..b518d123 100644 --- a/crates/handlers/src/oauth2/mod.rs +++ b/crates/handlers/src/oauth2/mod.rs @@ -70,7 +70,7 @@ pub(crate) fn generate_id_token( claims::SUB.insert(&mut claims, &browser_session.user.sub)?; claims::AUD.insert(&mut claims, client.client_id.clone())?; claims::IAT.insert(&mut claims, now)?; - claims::EXP.insert(&mut claims, now + Duration::hours(1))?; + claims::EXP.insert(&mut claims, now + Duration::try_hours(1).unwrap())?; if let Some(nonce) = grant.and_then(|grant| grant.nonce.as_ref()) { claims::NONCE.insert(&mut claims, nonce)?; diff --git a/crates/handlers/src/oauth2/revoke.rs b/crates/handlers/src/oauth2/revoke.rs index 524633b5..9e2d4c79 100644 --- a/crates/handlers/src/oauth2/revoke.rs +++ b/crates/handlers/src/oauth2/revoke.rs @@ -326,7 +326,7 @@ mod tests { &state.clock, &mut repo, &session, - Duration::minutes(5), + Duration::microseconds(5 * 60 * 1000 * 1000), ) .await .unwrap(); @@ -393,7 +393,7 @@ mod tests { &state.clock, &mut repo, &session, - Duration::minutes(5), + Duration::microseconds(5 * 60 * 1000 * 1000), ) .await .unwrap(); diff --git a/crates/handlers/src/oauth2/token.rs b/crates/handlers/src/oauth2/token.rs index 8f4bd3d8..4093d44e 100644 --- a/crates/handlers/src/oauth2/token.rs +++ b/crates/handlers/src/oauth2/token.rs @@ -365,7 +365,7 @@ async fn authorization_code_grant( debug!(%exchanged_at, %fulfilled_at, "Authorization code was already exchanged"); // Ending the session if the token was already exchanged more than 20s ago - if now - exchanged_at > Duration::seconds(20) { + if now - exchanged_at > Duration::microseconds(20 * 1000 * 1000) { debug!("Ending potentially compromised session"); let session = repo .oauth2_session() @@ -386,7 +386,7 @@ async fn authorization_code_grant( session_id, fulfilled_at, } => { - if now - fulfilled_at > Duration::minutes(10) { + if now - fulfilled_at > Duration::microseconds(10 * 60 * 1000 * 1000) { debug!("Code exchange took more than 10 minutes"); return Err(RouteError::InvalidGrant); } @@ -928,7 +928,7 @@ mod tests { assert!(state.is_access_token_valid(&access_token).await); // Now wait a bit - state.clock.advance(Duration::minutes(1)); + state.clock.advance(Duration::try_minutes(1).unwrap()); // Exchange it again, this it should fail let request = @@ -994,7 +994,9 @@ mod tests { repo.save().await.unwrap(); // Now wait a bit - state.clock.advance(Duration::minutes(15)); + state + .clock + .advance(Duration::microseconds(15 * 60 * 1000 * 1000)); // Exchange it, it should fail let request = @@ -1075,7 +1077,7 @@ mod tests { &state.clock, &mut repo, &session, - Duration::minutes(5), + Duration::microseconds(5 * 60 * 1000 * 1000), ) .await .unwrap(); @@ -1386,7 +1388,7 @@ mod tests { let ClientError { error, .. } = response.json(); assert_eq!(error, ClientErrorCode::AuthorizationPending); - state.clock.advance(Duration::hours(1)); + state.clock.advance(Duration::try_hours(1).unwrap()); // Poll again, it should be expired let request = diff --git a/crates/handlers/src/site_config.rs b/crates/handlers/src/site_config.rs index d52a6ebb..58c3668f 100644 --- a/crates/handlers/src/site_config.rs +++ b/crates/handlers/src/site_config.rs @@ -26,8 +26,8 @@ pub struct SiteConfig { impl Default for SiteConfig { fn default() -> Self { Self { - access_token_ttl: Duration::minutes(5), - compat_token_ttl: Duration::minutes(5), + access_token_ttl: Duration::microseconds(5 * 60 * 1000 * 1000), + compat_token_ttl: Duration::microseconds(5 * 60 * 1000 * 1000), tos_uri: None, } } diff --git a/crates/handlers/src/upstream_oauth2/cookie.rs b/crates/handlers/src/upstream_oauth2/cookie.rs index f8ffd6cf..323f62df 100644 --- a/crates/handlers/src/upstream_oauth2/cookie.rs +++ b/crates/handlers/src/upstream_oauth2/cookie.rs @@ -14,7 +14,7 @@ // TODO: move that to a standalone cookie manager -use chrono::{DateTime, Duration, NaiveDateTime, TimeZone, Utc}; +use chrono::{DateTime, Duration, Utc}; use mas_axum_utils::cookies::CookieJar; use mas_router::PostAuthAction; use mas_storage::Clock; @@ -26,7 +26,7 @@ use ulid::Ulid; static COOKIE_NAME: &str = "upstream-oauth2-sessions"; /// Sessions expire after 10 minutes -static SESSION_MAX_TIME_SECS: i64 = 60 * 10; +static SESSION_MAX_TIME: Duration = Duration::microseconds(10 * 60 * 1000 * 1000); #[derive(Serialize, Deserialize, Debug)] pub struct Payload { @@ -42,12 +42,10 @@ impl Payload { let Ok(ts) = self.session.timestamp_ms().try_into() else { return true; }; - let Some(when) = NaiveDateTime::from_timestamp_millis(ts) else { + let Some(when) = DateTime::from_timestamp_millis(ts) else { return true; }; - let when = Utc.from_utc_datetime(&when); - let max_age = Duration::seconds(SESSION_MAX_TIME_SECS); - now - when > max_age + now - when > SESSION_MAX_TIME } } @@ -184,7 +182,7 @@ mod tests { let first_state = "first-state"; let sessions = sessions.add(first_session, provider_a, first_state.into(), None); - let now = now + Duration::minutes(5); + let now = now + Duration::microseconds(5 * 60 * 1000 * 1000); let second_session = Ulid::from_datetime_with_source(now.into(), &mut rng); let second_state = "second-state"; @@ -203,7 +201,7 @@ mod tests { assert!(sessions.find_session(provider_a, second_state).is_err()); // Make the first session expire - let now = now + Duration::minutes(6); + let now = now + Duration::microseconds(6 * 60 * 1000 * 1000); let sessions = sessions.expire(now); assert!(sessions.find_session(provider_a, first_state).is_err()); assert_eq!( diff --git a/crates/jose/src/claims.rs b/crates/jose/src/claims.rs index cdb68c66..a3f96da1 100644 --- a/crates/jose/src/claims.rs +++ b/crates/jose/src/claims.rs @@ -203,7 +203,7 @@ impl TimeOptions { pub fn new(when: chrono::DateTime) -> Self { Self { when, - leeway: chrono::Duration::minutes(5), + leeway: chrono::Duration::microseconds(5 * 60 * 1000 * 1000), } } @@ -586,7 +586,7 @@ mod tests { let now = chrono::Utc .with_ymd_and_hms(2018, 1, 18, 1, 30, 22) .unwrap(); - let expiration = now + chrono::Duration::minutes(5); + let expiration = now + chrono::Duration::microseconds(5 * 60 * 1000 * 1000); let time_options = TimeOptions::new(now).leeway(chrono::Duration::zero()); let claims = serde_json::json!({ @@ -660,7 +660,7 @@ mod tests { } // Let's go back in time a bit - let now = now - chrono::Duration::minutes(1); + let now = now - chrono::Duration::microseconds(60 * 1000 * 1000); { // There is now a time variance between the two parties... @@ -686,7 +686,8 @@ mod tests { let mut claims = claims.clone(); // but no time variance is allowed. "iat" and "nbf" validation will fail - let time_options = TimeOptions::new(now).leeway(chrono::Duration::minutes(2)); + let time_options = + TimeOptions::new(now).leeway(chrono::Duration::microseconds(2 * 60 * 1000 * 1000)); assert!(IAT .extract_required_with_options(&mut claims, &time_options) .is_ok()); @@ -699,7 +700,7 @@ mod tests { } // Let's wait some time so it expires - let now = now + chrono::Duration::minutes(1 + 6); + let now = now + chrono::Duration::microseconds((1 + 6) * 60 * 1000 * 1000); { // At this point, the claims expired one minute ago @@ -723,7 +724,8 @@ mod tests { let mut claims = claims; // Same, but with a 2 minutes leeway should be fine then - let time_options = TimeOptions::new(now).leeway(chrono::Duration::minutes(2)); + let time_options = + TimeOptions::new(now).leeway(chrono::Duration::try_minutes(2).unwrap()); assert!(IAT .extract_required_with_options(&mut claims, &time_options) .is_ok()); diff --git a/crates/oauth2-types/src/requests.rs b/crates/oauth2-types/src/requests.rs index 76b16946..0558d805 100644 --- a/crates/oauth2-types/src/requests.rs +++ b/crates/oauth2-types/src/requests.rs @@ -366,7 +366,7 @@ pub struct DeviceAuthorizationRequest { /// The default value of the `interval` between polling requests, if it is not /// set. -pub const DEFAULT_DEVICE_AUTHORIZATION_INTERVAL_SECONDS: i64 = 5; +pub const DEFAULT_DEVICE_AUTHORIZATION_INTERVAL: Duration = Duration::microseconds(5 * 1000 * 1000); /// A successful response from the [Device Authorization Endpoint]. /// @@ -399,7 +399,7 @@ pub struct DeviceAuthorizationResponse { /// The minimum amount of time in seconds that the client should wait /// between polling requests to the token endpoint. /// - /// Defaults to [`DEFAULT_DEVICE_AUTHORIZATION_INTERVAL_SECONDS`]. + /// Defaults to [`DEFAULT_DEVICE_AUTHORIZATION_INTERVAL`]. #[serde_as(as = "Option>")] pub interval: Option, } @@ -408,11 +408,11 @@ impl DeviceAuthorizationResponse { /// The minimum amount of time in seconds that the client should wait /// between polling requests to the token endpoint. /// - /// Defaults to [`DEFAULT_DEVICE_AUTHORIZATION_INTERVAL_SECONDS`]. + /// Defaults to [`DEFAULT_DEVICE_AUTHORIZATION_INTERVAL`]. #[must_use] pub fn interval(&self) -> Duration { self.interval - .unwrap_or_else(|| Duration::seconds(DEFAULT_DEVICE_AUTHORIZATION_INTERVAL_SECONDS)) + .unwrap_or(DEFAULT_DEVICE_AUTHORIZATION_INTERVAL) } } diff --git a/crates/oidc-client/src/types/client_credentials.rs b/crates/oidc-client/src/types/client_credentials.rs index c7c6d04f..04fde1c2 100644 --- a/crates/oidc-client/src/types/client_credentials.rs +++ b/crates/oidc-client/src/types/client_credentials.rs @@ -399,7 +399,10 @@ fn prepare_claims( claims::SUB.insert(&mut claims, iss)?; claims::AUD.insert(&mut claims, aud)?; claims::IAT.insert(&mut claims, now)?; - claims::EXP.insert(&mut claims, now + Duration::minutes(5))?; + claims::EXP.insert( + &mut claims, + now + Duration::microseconds(5 * 60 * 1000 * 1000), + )?; let mut jti = [0u8; 16]; rng.fill(&mut jti); diff --git a/crates/oidc-client/tests/it/main.rs b/crates/oidc-client/tests/it/main.rs index 37717e7a..6edf90a7 100644 --- a/crates/oidc-client/tests/it/main.rs +++ b/crates/oidc-client/tests/it/main.rs @@ -105,7 +105,7 @@ fn id_token(issuer: &str) -> (IdToken, PublicJsonWebKeySet) { claims::IAT.insert(&mut claims, now).unwrap(); claims::EXP - .insert(&mut claims, now + Duration::hours(1)) + .insert(&mut claims, now + Duration::try_hours(1).unwrap()) .unwrap(); claims::AT_HASH diff --git a/crates/oidc-client/tests/it/requests/authorization_code.rs b/crates/oidc-client/tests/it/requests/authorization_code.rs index 4325e44e..134f7ea2 100644 --- a/crates/oidc-client/tests/it/requests/authorization_code.rs +++ b/crates/oidc-client/tests/it/requests/authorization_code.rs @@ -174,7 +174,7 @@ async fn pass_pushed_authorization_request() { .respond_with( ResponseTemplate::new(200).set_body_json(PushedAuthorizationResponse { request_uri: REQUEST_URI.to_owned(), - expires_in: Duration::seconds(30), + expires_in: Duration::microseconds(30 * 1000 * 1000), }), ) .mount(&mock_server) diff --git a/crates/oidc-client/tests/it/requests/jose.rs b/crates/oidc-client/tests/it/requests/jose.rs index e29dd0f8..d9a8806c 100644 --- a/crates/oidc-client/tests/it/requests/jose.rs +++ b/crates/oidc-client/tests/it/requests/jose.rs @@ -68,11 +68,11 @@ fn id_token( if flag == Some(IdTokenFlag::WrongExpiration) { claims::EXP - .insert(&mut claims, now - Duration::hours(1)) + .insert(&mut claims, now - Duration::try_hours(1).unwrap()) .unwrap(); } else { claims::EXP - .insert(&mut claims, now + Duration::hours(1)) + .insert(&mut claims, now + Duration::try_hours(1).unwrap()) .unwrap(); } @@ -229,7 +229,7 @@ async fn fail_verify_id_token_wrong_auth_time() { let issuer = "http://localhost/"; let now = now(); let (auth_id_token, _) = id_token(issuer, None, Some(now)); - let (id_token, jwks) = id_token(issuer, None, Some(now + Duration::hours(1))); + let (id_token, jwks) = id_token(issuer, None, Some(now + Duration::try_hours(1).unwrap())); let verification_data = JwtVerificationData { issuer, diff --git a/crates/storage-pg/src/app_session.rs b/crates/storage-pg/src/app_session.rs index af1ebbb6..51a20a6e 100644 --- a/crates/storage-pg/src/app_session.rs +++ b/crates/storage-pg/src/app_session.rs @@ -608,7 +608,7 @@ mod tests { // We're moving the clock forward by 1 minute between each session to ensure // we're getting consistent ordering in lists. - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); let oauth_session = repo .oauth2_session() diff --git a/crates/storage-pg/src/compat/mod.rs b/crates/storage-pg/src/compat/mod.rs index 418824fe..092b8c8b 100644 --- a/crates/storage-pg/src/compat/mod.rs +++ b/crates/storage-pg/src/compat/mod.rs @@ -321,7 +321,7 @@ mod tests { &clock, &session, FIRST_TOKEN.to_owned(), - Some(Duration::minutes(1)), + Some(Duration::try_minutes(1).unwrap()), ) .await .unwrap(); @@ -341,7 +341,7 @@ mod tests { &clock, &session, FIRST_TOKEN.to_owned(), - Some(Duration::minutes(1)), + Some(Duration::try_minutes(1).unwrap()), ) .await .is_err()); @@ -374,7 +374,7 @@ mod tests { // Token is currently valid assert!(token.is_valid(clock.now())); - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); // Token should have expired assert!(!token.is_valid(clock.now())); diff --git a/crates/storage-pg/src/oauth2/access_token.rs b/crates/storage-pg/src/oauth2/access_token.rs index 71df24cf..f07b8053 100644 --- a/crates/storage-pg/src/oauth2/access_token.rs +++ b/crates/storage-pg/src/oauth2/access_token.rs @@ -208,7 +208,7 @@ impl<'c> OAuth2AccessTokenRepository for PgOAuth2AccessTokenRepository<'c> { async fn cleanup_expired(&mut self, clock: &dyn Clock) -> Result { // Cleanup token which expired more than 15 minutes ago - let threshold = clock.now() - Duration::minutes(15); + let threshold = clock.now() - Duration::microseconds(15 * 60 * 1000 * 1000); let res = sqlx::query!( r#" DELETE FROM oauth2_access_tokens diff --git a/crates/storage-pg/src/oauth2/mod.rs b/crates/storage-pg/src/oauth2/mod.rs index 0913e832..a6b3ca55 100644 --- a/crates/storage-pg/src/oauth2/mod.rs +++ b/crates/storage-pg/src/oauth2/mod.rs @@ -272,7 +272,7 @@ mod tests { &clock, &session, "aabbcc".to_owned(), - Some(Duration::minutes(5)), + Some(Duration::try_minutes(5).unwrap()), ) .await .unwrap(); @@ -343,11 +343,11 @@ mod tests { assert_eq!(refresh_token, refresh_token_lookup); assert!(access_token.is_valid(clock.now())); - clock.advance(Duration::minutes(6)); + clock.advance(Duration::try_minutes(6).unwrap()); assert!(!access_token.is_valid(clock.now())); // XXX: we might want to create a new access token - clock.advance(Duration::minutes(-6)); // Go back in time + clock.advance(Duration::try_minutes(-6).unwrap()); // Go back in time assert!(access_token.is_valid(clock.now())); // Mark the access token as revoked @@ -487,28 +487,28 @@ mod tests { .add_from_browser_session(&mut rng, &clock, &client1, &user1_session, scope.clone()) .await .unwrap(); - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); let session12 = repo .oauth2_session() .add_from_browser_session(&mut rng, &clock, &client1, &user2_session, scope.clone()) .await .unwrap(); - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); let session21 = repo .oauth2_session() .add_from_browser_session(&mut rng, &clock, &client2, &user1_session, scope2.clone()) .await .unwrap(); - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); let session22 = repo .oauth2_session() .add_from_browser_session(&mut rng, &clock, &client2, &user2_session, scope2.clone()) .await .unwrap(); - clock.advance(Duration::minutes(1)); + clock.advance(Duration::try_minutes(1).unwrap()); // We're also finishing two of the sessions let session11 = repo @@ -775,7 +775,7 @@ mod tests { scope: scope.clone(), device_code: device_code.to_owned(), user_code: user_code.to_owned(), - expires_in: Duration::minutes(5), + expires_in: Duration::try_minutes(5).unwrap(), ip_address: None, user_agent: None, }, @@ -880,7 +880,7 @@ mod tests { scope: scope.clone(), device_code: "second_devicecode".to_owned(), user_code: "second_usercode".to_owned(), - expires_in: Duration::minutes(5), + expires_in: Duration::try_minutes(5).unwrap(), ip_address: None, user_agent: None, }, diff --git a/crates/storage-pg/src/upstream_oauth2/mod.rs b/crates/storage-pg/src/upstream_oauth2/mod.rs index 3b41998f..06596ffe 100644 --- a/crates/storage-pg/src/upstream_oauth2/mod.rs +++ b/crates/storage-pg/src/upstream_oauth2/mod.rs @@ -266,7 +266,7 @@ mod tests { .await .unwrap(); ids.push(provider.id); - clock.advance(Duration::seconds(10)); + clock.advance(Duration::microseconds(10 * 1000 * 1000)); } // Now we have 20 providers diff --git a/crates/storage-pg/src/user/tests.rs b/crates/storage-pg/src/user/tests.rs index 3e7bc090..631b647a 100644 --- a/crates/storage-pg/src/user/tests.rs +++ b/crates/storage-pg/src/user/tests.rs @@ -191,7 +191,7 @@ async fn test_user_email_repo(pool: PgPool) { &mut rng, &clock, &user_email, - Duration::hours(8), + Duration::try_hours(8).unwrap(), CODE.to_owned(), ) .await @@ -208,7 +208,7 @@ async fn test_user_email_repo(pool: PgPool) { &mut rng, &clock, &user_email, - Duration::hours(8), + Duration::try_hours(8).unwrap(), CODE2.to_owned(), ) .await @@ -395,7 +395,7 @@ async fn test_user_password_repo(pool: PgPool) { // Getting the last inserted password is based on the clock, so we need to // advance it - clock.advance(Duration::seconds(10)); + clock.advance(Duration::microseconds(10 * 1000 * 1000)); let second_password = repo .user_password() diff --git a/crates/storage/src/clock.rs b/crates/storage/src/clock.rs index a338d1d8..d50903b3 100644 --- a/crates/storage/src/clock.rs +++ b/crates/storage/src/clock.rs @@ -66,9 +66,9 @@ impl Clock for SystemClock { /// let t2 = clock.now(); /// assert_eq!(t1, t2); /// -/// clock.advance(Duration::seconds(10)); +/// clock.advance(Duration::microseconds(10 * 1000 * 1000)); /// let t3 = clock.now(); -/// assert_eq!(t2 + Duration::seconds(10), t3); +/// assert_eq!(t2 + Duration::microseconds(10 * 1000 * 1000), t3); /// ``` pub struct MockClock { timestamp: AtomicI64, @@ -121,9 +121,9 @@ mod tests { assert_eq!(first, second); // Clock can be advanced by a fixed duration - clock.advance(Duration::seconds(10)); + clock.advance(Duration::microseconds(10 * 1000 * 1000)); let third = clock.now(); - assert_eq!(first + Duration::seconds(10), third); + assert_eq!(first + Duration::microseconds(10 * 1000 * 1000), third); } #[test] diff --git a/crates/tasks/src/email.rs b/crates/tasks/src/email.rs index 99418fc0..589340e6 100644 --- a/crates/tasks/src/email.rs +++ b/crates/tasks/src/email.rs @@ -69,7 +69,13 @@ async fn verify_email( // Save the verification code in the database let verification = repo .user_email() - .add_verification_code(&mut rng, &clock, &user_email, Duration::hours(8), code) + .add_verification_code( + &mut rng, + &clock, + &user_email, + Duration::try_hours(8).unwrap(), + code, + ) .await?; // And send the verification email diff --git a/crates/tasks/src/storage/postgres.rs b/crates/tasks/src/storage/postgres.rs index dc61f2b3..4836f09c 100644 --- a/crates/tasks/src/storage/postgres.rs +++ b/crates/tasks/src/storage/postgres.rs @@ -337,7 +337,7 @@ where .as_secs() .try_into() .map_err(|e| StorageError::Database(Box::new(e)))?; - let wait = chrono::Duration::seconds(wait); + let wait = chrono::Duration::microseconds(wait * 1000 * 1000); // TODO: should we use a clock here? #[allow(clippy::disallowed_methods)] let run_at = Utc::now().add(wait); diff --git a/crates/templates/src/context.rs b/crates/templates/src/context.rs index 0c99a1bf..d7788864 100644 --- a/crates/templates/src/context.rs +++ b/crates/templates/src/context.rs @@ -626,8 +626,8 @@ impl TemplateContext for PolicyViolationContext { scope: [OPENID].into_iter().collect(), user_code: Alphanumeric.sample_string(rng, 6).to_uppercase(), device_code: Alphanumeric.sample_string(rng, 32), - created_at: now - Duration::minutes(5), - expires_at: now + Duration::minutes(25), + created_at: now - Duration::try_minutes(5).unwrap(), + expires_at: now + Duration::try_minutes(25).unwrap(), ip_address: None, user_agent: None, }, @@ -1161,8 +1161,8 @@ impl TemplateContext for DeviceConsentContext { scope: [OPENID].into_iter().collect(), user_code: Alphanumeric.sample_string(rng, 6).to_uppercase(), device_code: Alphanumeric.sample_string(rng, 32), - created_at: now - Duration::minutes(5), - expires_at: now + Duration::minutes(25), + created_at: now - Duration::try_minutes(5).unwrap(), + expires_at: now + Duration::try_minutes(25).unwrap(), ip_address: Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))), user_agent: Some(UserAgent::parse("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36".to_owned())), };