1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Stop using Utc::now in templates samples

This commit is contained in:
Quentin Gliech
2022-10-24 09:33:24 +02:00
parent 44d09b68e7
commit f0d95a7613
5 changed files with 74 additions and 69 deletions

View File

@ -15,6 +15,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use mas_storage::Clock;
use mas_templates::Templates; use mas_templates::Templates;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -57,10 +58,11 @@ impl Options {
} }
SC::Check { path, skip_builtin } => { SC::Check { path, skip_builtin } => {
let clock = Clock::default();
let url_builder = mas_router::UrlBuilder::new("https://example.com/".parse()?); let url_builder = mas_router::UrlBuilder::new("https://example.com/".parse()?);
let templates = let templates =
Templates::load(Some(path.into()), !skip_builtin, url_builder).await?; Templates::load(Some(path.into()), !skip_builtin, url_builder).await?;
templates.check_render().await?; templates.check_render(clock.now()).await?;
Ok(()) Ok(())
} }

View File

@ -31,7 +31,7 @@ where
T::UserData: Default, T::UserData: Default,
{ {
#[must_use] #[must_use]
pub fn samples() -> Vec<Self> { pub fn samples(_now: chrono::DateTime<Utc>) -> Vec<Self> {
vec![User { vec![User {
data: Default::default(), data: Default::default(),
username: "john".to_owned(), username: "john".to_owned(),
@ -105,13 +105,13 @@ where
T::UserData: Default, T::UserData: Default,
{ {
#[must_use] #[must_use]
pub fn samples() -> Vec<Self> { pub fn samples(now: chrono::DateTime<Utc>) -> Vec<Self> {
User::<T>::samples() User::<T>::samples(now)
.into_iter() .into_iter()
.map(|user| BrowserSession { .map(|user| BrowserSession {
data: Default::default(), data: Default::default(),
user, user,
created_at: Utc::now(), created_at: now,
last_authentication: None, last_authentication: None,
}) })
.collect() .collect()
@ -143,18 +143,18 @@ where
T::UserEmailData: Default, T::UserEmailData: Default,
{ {
#[must_use] #[must_use]
pub fn samples() -> Vec<Self> { pub fn samples(now: chrono::DateTime<Utc>) -> Vec<Self> {
vec![ vec![
Self { Self {
data: T::UserEmailData::default(), data: T::UserEmailData::default(),
email: "alice@example.com".to_owned(), email: "alice@example.com".to_owned(),
created_at: Utc::now(), created_at: now,
confirmed_at: Some(Utc::now()), confirmed_at: Some(now),
}, },
Self { Self {
data: T::UserEmailData::default(), data: T::UserEmailData::default(),
email: "bob@example.com".to_owned(), email: "bob@example.com".to_owned(),
created_at: Utc::now(), created_at: now,
confirmed_at: None, confirmed_at: None,
}, },
] ]
@ -195,13 +195,13 @@ where
T::UserEmailData: Default + Clone, T::UserEmailData: Default + Clone,
{ {
#[must_use] #[must_use]
pub fn samples() -> Vec<Self> { pub fn samples(now: chrono::DateTime<Utc>) -> Vec<Self> {
let states = [ let states = [
UserEmailVerificationState::AlreadyUsed { UserEmailVerificationState::AlreadyUsed {
when: Utc::now() - Duration::minutes(5), when: now - Duration::minutes(5),
}, },
UserEmailVerificationState::Expired { UserEmailVerificationState::Expired {
when: Utc::now() - Duration::hours(5), when: now - Duration::hours(5),
}, },
UserEmailVerificationState::Valid, UserEmailVerificationState::Valid,
]; ];
@ -209,11 +209,11 @@ where
states states
.into_iter() .into_iter()
.flat_map(|state| { .flat_map(|state| {
UserEmail::samples().into_iter().map(move |email| Self { UserEmail::samples(now).into_iter().map(move |email| Self {
data: Default::default(), data: Default::default(),
code: "123456".to_owned(), code: "123456".to_owned(),
email, email,
created_at: Utc::now() - Duration::minutes(10), created_at: now - Duration::minutes(10),
state: state.clone(), state: state.clone(),
}) })
}) })

View File

@ -77,13 +77,13 @@ pub trait TemplateContext: Serialize {
/// ///
/// This is then used to check for template validity in unit tests and in /// This is then used to check for template validity in unit tests and in
/// the CLI (`cargo run -- templates check`) /// the CLI (`cargo run -- templates check`)
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized; Self: Sized;
} }
impl TemplateContext for () { impl TemplateContext for () {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -101,11 +101,11 @@ pub struct WithCsrf<T> {
} }
impl<T: TemplateContext> TemplateContext for WithCsrf<T> { impl<T: TemplateContext> TemplateContext for WithCsrf<T> {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
T::sample() T::sample(now)
.into_iter() .into_iter()
.map(|inner| WithCsrf { .map(|inner| WithCsrf {
csrf_token: "fake_csrf_token".into(), csrf_token: "fake_csrf_token".into(),
@ -125,14 +125,14 @@ pub struct WithSession<T> {
} }
impl<T: TemplateContext> TemplateContext for WithSession<T> { impl<T: TemplateContext> TemplateContext for WithSession<T> {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
BrowserSession::samples() BrowserSession::samples(now)
.into_iter() .into_iter()
.flat_map(|session| { .flat_map(|session| {
T::sample().into_iter().map(move |inner| WithSession { T::sample(now).into_iter().map(move |inner| WithSession {
current_session: session.clone(), current_session: session.clone(),
inner, inner,
}) })
@ -151,16 +151,16 @@ pub struct WithOptionalSession<T> {
} }
impl<T: TemplateContext> TemplateContext for WithOptionalSession<T> { impl<T: TemplateContext> TemplateContext for WithOptionalSession<T> {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
BrowserSession::samples() BrowserSession::samples(now)
.into_iter() .into_iter()
.map(Some) // Wrap all samples in an Option .map(Some) // Wrap all samples in an Option
.chain(std::iter::once(None)) // Add the "None" option .chain(std::iter::once(None)) // Add the "None" option
.flat_map(|session| { .flat_map(|session| {
T::sample() T::sample(now)
.into_iter() .into_iter()
.map(move |inner| WithOptionalSession { .map(move |inner| WithOptionalSession {
current_session: session.clone(), current_session: session.clone(),
@ -188,7 +188,7 @@ impl Serialize for EmptyContext {
} }
impl TemplateContext for EmptyContext { impl TemplateContext for EmptyContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -212,7 +212,7 @@ impl IndexContext {
} }
impl TemplateContext for IndexContext { impl TemplateContext for IndexContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -274,7 +274,7 @@ pub struct LoginContext {
} }
impl TemplateContext for LoginContext { impl TemplateContext for LoginContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -348,7 +348,7 @@ pub struct RegisterContext {
} }
impl TemplateContext for RegisterContext { impl TemplateContext for RegisterContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -392,7 +392,7 @@ pub struct ConsentContext {
} }
impl TemplateContext for ConsentContext { impl TemplateContext for ConsentContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -423,7 +423,7 @@ pub struct PolicyViolationContext {
} }
impl TemplateContext for PolicyViolationContext { impl TemplateContext for PolicyViolationContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -471,7 +471,7 @@ pub struct ReauthContext {
} }
impl TemplateContext for ReauthContext { impl TemplateContext for ReauthContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -510,7 +510,7 @@ pub struct CompatSsoContext {
} }
impl TemplateContext for CompatSsoContext { impl TemplateContext for CompatSsoContext {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -519,10 +519,10 @@ impl TemplateContext for CompatSsoContext {
data: (), data: (),
redirect_uri: Url::parse("https://app.element.io/").unwrap(), redirect_uri: Url::parse("https://app.element.io/").unwrap(),
login_token: "abcdefghijklmnopqrstuvwxyz012345".into(), login_token: "abcdefghijklmnopqrstuvwxyz012345".into(),
created_at: Utc::now(), created_at: now,
state: CompatSsoLoginState::Pending, 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 { impl TemplateContext for AccountContext {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
let emails: Vec<UserEmail<()>> = UserEmail::samples(); let emails: Vec<UserEmail<()>> = UserEmail::samples(now);
vec![Self::new(5, emails)] vec![Self::new(5, emails)]
} }
} }
@ -588,11 +588,11 @@ impl<T: StorageBackend> AccountEmailsContext<T> {
} }
impl<T: StorageBackend> TemplateContext for AccountEmailsContext<T> { impl<T: StorageBackend> TemplateContext for AccountEmailsContext<T> {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
let emails: Vec<UserEmail<T>> = UserEmail::samples(); let emails: Vec<UserEmail<T>> = UserEmail::samples(now);
vec![Self::new(emails)] vec![Self::new(emails)]
} }
} }
@ -613,17 +613,17 @@ impl EmailVerificationContext {
} }
impl TemplateContext for EmailVerificationContext { impl TemplateContext for EmailVerificationContext {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
User::samples() User::samples(now)
.into_iter() .into_iter()
.map(|user| { .map(|user| {
let email = UserEmail { let email = UserEmail {
data: (), data: (),
email: "foobar@example.com".to_owned(), email: "foobar@example.com".to_owned(),
created_at: Utc::now(), created_at: now,
confirmed_at: None, confirmed_at: None,
}; };
@ -631,7 +631,7 @@ impl TemplateContext for EmailVerificationContext {
data: (), data: (),
code: "123456".to_owned(), code: "123456".to_owned(),
email, email,
created_at: Utc::now(), created_at: now,
state: mas_data_model::UserEmailVerificationState::Valid, state: mas_data_model::UserEmailVerificationState::Valid,
}; };
@ -685,14 +685,14 @@ impl EmailVerificationPageContext {
} }
impl TemplateContext for EmailVerificationPageContext { impl TemplateContext for EmailVerificationPageContext {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
let email = UserEmail { let email = UserEmail {
data: (), data: (),
email: "foobar@example.com".to_owned(), email: "foobar@example.com".to_owned(),
created_at: Utc::now(), created_at: now,
confirmed_at: None, confirmed_at: None,
}; };
@ -740,7 +740,7 @@ impl EmailAddContext {
} }
impl TemplateContext for EmailAddContext { impl TemplateContext for EmailAddContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -756,11 +756,11 @@ pub struct FormPostContext<T> {
} }
impl<T: TemplateContext> TemplateContext for FormPostContext<T> { impl<T: TemplateContext> TemplateContext for FormPostContext<T> {
fn sample() -> Vec<Self> fn sample(now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {
let sample_params = T::sample(); let sample_params = T::sample(now);
sample_params sample_params
.into_iter() .into_iter()
.map(|params| FormPostContext { .map(|params| FormPostContext {
@ -790,7 +790,7 @@ pub struct ErrorContext {
} }
impl TemplateContext for ErrorContext { impl TemplateContext for ErrorContext {
fn sample() -> Vec<Self> fn sample(_now: chrono::DateTime<Utc>) -> Vec<Self>
where where
Self: Sized, Self: Sized,
{ {

View File

@ -362,24 +362,24 @@ register_templates! {
impl Templates { impl Templates {
/// Render all templates with the generated samples to check if they render /// Render all templates with the generated samples to check if they render
/// properly /// properly
pub async fn check_render(&self) -> anyhow::Result<()> { pub async fn check_render(&self, now: chrono::DateTime<chrono::Utc>) -> anyhow::Result<()> {
check::render_login(self).await?; check::render_login(self, now).await?;
check::render_register(self).await?; check::render_register(self, now).await?;
check::render_consent(self).await?; check::render_consent(self, now).await?;
check::render_policy_violation(self).await?; check::render_policy_violation(self, now).await?;
check::render_sso_login(self).await?; check::render_sso_login(self, now).await?;
check::render_index(self).await?; check::render_index(self, now).await?;
check::render_account_index(self).await?; check::render_account_index(self, now).await?;
check::render_account_password(self).await?; check::render_account_password(self, now).await?;
check::render_account_emails::<()>(self).await?; check::render_account_emails::<()>(self, now).await?;
check::render_account_add_email(self).await?; check::render_account_add_email(self, now).await?;
check::render_account_verify_email(self).await?; check::render_account_verify_email(self, now).await?;
check::render_reauth(self).await?; check::render_reauth(self, now).await?;
check::render_form_post::<EmptyContext>(self).await?; check::render_form_post::<EmptyContext>(self, now).await?;
check::render_error(self).await?; check::render_error(self, now).await?;
check::render_email_verification_txt(self).await?; check::render_email_verification_txt(self, now).await?;
check::render_email_verification_html(self).await?; check::render_email_verification_html(self, now).await?;
check::render_email_verification_subject(self).await?; check::render_email_verification_subject(self, now).await?;
Ok(()) Ok(())
} }
} }
@ -390,8 +390,11 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn check_builtin_templates() { 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 url_builder = UrlBuilder::new("https://example.com/".parse().unwrap());
let templates = Templates::load(None, true, url_builder).await.unwrap(); let templates = Templates::load(None, true, url_builder).await.unwrap();
templates.check_render().await.unwrap(); templates.check_render(now).await.unwrap();
} }
} }

View File

@ -96,9 +96,9 @@ macro_rules! register_templates {
#[doc = concat!("Render the `", $template, "` template with sample contexts")] #[doc = concat!("Render the `", $template, "` template with sample contexts")]
pub async fn $name pub async fn $name
$(< $( $lt $( : $clt $(+ $dlt )* + TemplateContext )? ),+ >)? $(< $( $lt $( : $clt $(+ $dlt )* + TemplateContext )? ),+ >)?
(templates: &Templates) (templates: &Templates, now: chrono::DateTime<chrono::Utc>)
-> anyhow::Result<()> { -> anyhow::Result<()> {
let samples: Vec< $param > = TemplateContext::sample(); let samples: Vec< $param > = TemplateContext::sample(now);
let name = $template; let name = $template;
for sample in samples { for sample in samples {