From f0d95a76137a041d26422c85f8860bd03b2df1da Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 24 Oct 2022 09:33:24 +0200 Subject: [PATCH] Stop using Utc::now in templates samples --- crates/cli/src/commands/templates.rs | 4 +- crates/data-model/src/users.rs | 26 +++++------ crates/templates/src/context.rs | 68 ++++++++++++++-------------- crates/templates/src/lib.rs | 41 +++++++++-------- crates/templates/src/macros.rs | 4 +- 5 files changed, 74 insertions(+), 69 deletions(-) diff --git a/crates/cli/src/commands/templates.rs b/crates/cli/src/commands/templates.rs index c4639be7..74689306 100644 --- a/crates/cli/src/commands/templates.rs +++ b/crates/cli/src/commands/templates.rs @@ -15,6 +15,7 @@ use std::path::PathBuf; use clap::Parser; +use mas_storage::Clock; use mas_templates::Templates; #[derive(Parser, Debug)] @@ -57,10 +58,11 @@ impl Options { } SC::Check { path, skip_builtin } => { + let clock = Clock::default(); let url_builder = mas_router::UrlBuilder::new("https://example.com/".parse()?); let templates = Templates::load(Some(path.into()), !skip_builtin, url_builder).await?; - templates.check_render().await?; + templates.check_render(clock.now()).await?; Ok(()) } diff --git a/crates/data-model/src/users.rs b/crates/data-model/src/users.rs index 90d034b1..cd2b233e 100644 --- a/crates/data-model/src/users.rs +++ b/crates/data-model/src/users.rs @@ -31,7 +31,7 @@ where T::UserData: Default, { #[must_use] - pub fn samples() -> Vec { + pub fn samples(_now: chrono::DateTime) -> Vec { vec![User { data: Default::default(), username: "john".to_owned(), @@ -105,13 +105,13 @@ where T::UserData: Default, { #[must_use] - pub fn samples() -> Vec { - User::::samples() + pub fn samples(now: chrono::DateTime) -> Vec { + User::::samples(now) .into_iter() .map(|user| BrowserSession { data: Default::default(), user, - created_at: Utc::now(), + created_at: now, last_authentication: None, }) .collect() @@ -143,18 +143,18 @@ where T::UserEmailData: Default, { #[must_use] - pub fn samples() -> Vec { + pub fn samples(now: chrono::DateTime) -> Vec { vec![ Self { data: T::UserEmailData::default(), email: "alice@example.com".to_owned(), - created_at: Utc::now(), - confirmed_at: Some(Utc::now()), + created_at: now, + confirmed_at: Some(now), }, Self { data: T::UserEmailData::default(), email: "bob@example.com".to_owned(), - created_at: Utc::now(), + created_at: now, confirmed_at: None, }, ] @@ -195,13 +195,13 @@ where T::UserEmailData: Default + Clone, { #[must_use] - pub fn samples() -> Vec { + pub fn samples(now: chrono::DateTime) -> Vec { let states = [ UserEmailVerificationState::AlreadyUsed { - when: Utc::now() - Duration::minutes(5), + when: now - Duration::minutes(5), }, UserEmailVerificationState::Expired { - when: Utc::now() - Duration::hours(5), + when: now - Duration::hours(5), }, UserEmailVerificationState::Valid, ]; @@ -209,11 +209,11 @@ where states .into_iter() .flat_map(|state| { - UserEmail::samples().into_iter().map(move |email| Self { + UserEmail::samples(now).into_iter().map(move |email| Self { data: Default::default(), code: "123456".to_owned(), email, - created_at: Utc::now() - Duration::minutes(10), + created_at: now - Duration::minutes(10), state: state.clone(), }) }) diff --git a/crates/templates/src/context.rs b/crates/templates/src/context.rs index 9fd46fcc..e9aba32a 100644 --- a/crates/templates/src/context.rs +++ b/crates/templates/src/context.rs @@ -77,13 +77,13 @@ pub trait TemplateContext: Serialize { /// /// This is then used to check for template validity in unit tests and in /// the CLI (`cargo run -- templates check`) - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized; } impl TemplateContext for () { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -101,11 +101,11 @@ pub struct WithCsrf { } impl TemplateContext for WithCsrf { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - T::sample() + T::sample(now) .into_iter() .map(|inner| WithCsrf { csrf_token: "fake_csrf_token".into(), @@ -125,14 +125,14 @@ pub struct WithSession { } impl TemplateContext for WithSession { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - BrowserSession::samples() + BrowserSession::samples(now) .into_iter() .flat_map(|session| { - T::sample().into_iter().map(move |inner| WithSession { + T::sample(now).into_iter().map(move |inner| WithSession { current_session: session.clone(), inner, }) @@ -151,16 +151,16 @@ pub struct WithOptionalSession { } impl TemplateContext for WithOptionalSession { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - BrowserSession::samples() + BrowserSession::samples(now) .into_iter() .map(Some) // Wrap all samples in an Option .chain(std::iter::once(None)) // Add the "None" option .flat_map(|session| { - T::sample() + T::sample(now) .into_iter() .map(move |inner| WithOptionalSession { current_session: session.clone(), @@ -188,7 +188,7 @@ impl Serialize for EmptyContext { } impl TemplateContext for EmptyContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -212,7 +212,7 @@ impl IndexContext { } impl TemplateContext for IndexContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -274,7 +274,7 @@ pub struct LoginContext { } impl TemplateContext for LoginContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -348,7 +348,7 @@ pub struct RegisterContext { } impl TemplateContext for RegisterContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -392,7 +392,7 @@ pub struct ConsentContext { } impl TemplateContext for ConsentContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -423,7 +423,7 @@ pub struct PolicyViolationContext { } impl TemplateContext for PolicyViolationContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -471,7 +471,7 @@ pub struct ReauthContext { } impl TemplateContext for ReauthContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -510,7 +510,7 @@ pub struct CompatSsoContext { } impl TemplateContext for CompatSsoContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { @@ -519,10 +519,10 @@ impl TemplateContext for CompatSsoContext { data: (), redirect_uri: Url::parse("https://app.element.io/").unwrap(), login_token: "abcdefghijklmnopqrstuvwxyz012345".into(), - created_at: Utc::now(), + created_at: now, state: CompatSsoLoginState::Pending, }, - action: PostAuthAction::ContinueCompatSsoLogin { data: Ulid::new() }, + action: PostAuthAction::ContinueCompatSsoLogin { data: Ulid::nil() }, }] } } @@ -563,11 +563,11 @@ impl AccountContext { } impl TemplateContext for AccountContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - let emails: Vec> = UserEmail::samples(); + let emails: Vec> = UserEmail::samples(now); vec![Self::new(5, emails)] } } @@ -588,11 +588,11 @@ impl AccountEmailsContext { } impl TemplateContext for AccountEmailsContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - let emails: Vec> = UserEmail::samples(); + let emails: Vec> = UserEmail::samples(now); vec![Self::new(emails)] } } @@ -613,17 +613,17 @@ impl EmailVerificationContext { } impl TemplateContext for EmailVerificationContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - User::samples() + User::samples(now) .into_iter() .map(|user| { let email = UserEmail { data: (), email: "foobar@example.com".to_owned(), - created_at: Utc::now(), + created_at: now, confirmed_at: None, }; @@ -631,7 +631,7 @@ impl TemplateContext for EmailVerificationContext { data: (), code: "123456".to_owned(), email, - created_at: Utc::now(), + created_at: now, state: mas_data_model::UserEmailVerificationState::Valid, }; @@ -685,14 +685,14 @@ impl EmailVerificationPageContext { } impl TemplateContext for EmailVerificationPageContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { let email = UserEmail { data: (), email: "foobar@example.com".to_owned(), - created_at: Utc::now(), + created_at: now, confirmed_at: None, }; @@ -740,7 +740,7 @@ impl EmailAddContext { } impl TemplateContext for EmailAddContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { @@ -756,11 +756,11 @@ pub struct FormPostContext { } impl TemplateContext for FormPostContext { - fn sample() -> Vec + fn sample(now: chrono::DateTime) -> Vec where Self: Sized, { - let sample_params = T::sample(); + let sample_params = T::sample(now); sample_params .into_iter() .map(|params| FormPostContext { @@ -790,7 +790,7 @@ pub struct ErrorContext { } impl TemplateContext for ErrorContext { - fn sample() -> Vec + fn sample(_now: chrono::DateTime) -> Vec where Self: Sized, { diff --git a/crates/templates/src/lib.rs b/crates/templates/src/lib.rs index c1deade1..793067e7 100644 --- a/crates/templates/src/lib.rs +++ b/crates/templates/src/lib.rs @@ -362,24 +362,24 @@ register_templates! { impl Templates { /// Render all templates with the generated samples to check if they render /// properly - pub async fn check_render(&self) -> anyhow::Result<()> { - check::render_login(self).await?; - check::render_register(self).await?; - check::render_consent(self).await?; - check::render_policy_violation(self).await?; - check::render_sso_login(self).await?; - check::render_index(self).await?; - check::render_account_index(self).await?; - check::render_account_password(self).await?; - check::render_account_emails::<()>(self).await?; - check::render_account_add_email(self).await?; - check::render_account_verify_email(self).await?; - check::render_reauth(self).await?; - check::render_form_post::(self).await?; - check::render_error(self).await?; - check::render_email_verification_txt(self).await?; - check::render_email_verification_html(self).await?; - check::render_email_verification_subject(self).await?; + pub async fn check_render(&self, now: chrono::DateTime) -> anyhow::Result<()> { + check::render_login(self, now).await?; + check::render_register(self, now).await?; + check::render_consent(self, now).await?; + check::render_policy_violation(self, now).await?; + check::render_sso_login(self, now).await?; + check::render_index(self, now).await?; + check::render_account_index(self, now).await?; + check::render_account_password(self, now).await?; + check::render_account_emails::<()>(self, now).await?; + check::render_account_add_email(self, now).await?; + check::render_account_verify_email(self, now).await?; + check::render_reauth(self, now).await?; + check::render_form_post::(self, now).await?; + check::render_error(self, now).await?; + check::render_email_verification_txt(self, now).await?; + check::render_email_verification_html(self, now).await?; + check::render_email_verification_subject(self, now).await?; Ok(()) } } @@ -390,8 +390,11 @@ mod tests { #[tokio::test] async fn check_builtin_templates() { + #[allow(clippy::disallowed_methods)] + let now = chrono::Utc::now(); + let url_builder = UrlBuilder::new("https://example.com/".parse().unwrap()); let templates = Templates::load(None, true, url_builder).await.unwrap(); - templates.check_render().await.unwrap(); + templates.check_render(now).await.unwrap(); } } diff --git a/crates/templates/src/macros.rs b/crates/templates/src/macros.rs index dcd65bf2..7226b548 100644 --- a/crates/templates/src/macros.rs +++ b/crates/templates/src/macros.rs @@ -96,9 +96,9 @@ macro_rules! register_templates { #[doc = concat!("Render the `", $template, "` template with sample contexts")] pub async fn $name $(< $( $lt $( : $clt $(+ $dlt )* + TemplateContext )? ),+ >)? - (templates: &Templates) + (templates: &Templates, now: chrono::DateTime) -> anyhow::Result<()> { - let samples: Vec< $param > = TemplateContext::sample(); + let samples: Vec< $param > = TemplateContext::sample(now); let name = $template; for sample in samples {