diff options
Diffstat (limited to 'src/boot')
| -rw-r--r-- | src/boot/app.rs | 23 | ||||
| -rw-r--r-- | src/boot/handlers/boot/test.rs | 68 |
2 files changed, 90 insertions, 1 deletions
diff --git a/src/boot/app.rs b/src/boot/app.rs index 0ed5d1b..543429f 100644 --- a/src/boot/app.rs +++ b/src/boot/app.rs @@ -4,10 +4,12 @@ use sqlx::sqlite::SqlitePool; use super::Snapshot; use crate::{ conversation::{self, repo::Provider as _}, + db::NotFound, event::{Event, Sequence, repo::Provider as _}, message::{self, repo::Provider as _}, name, user::{self, repo::Provider as _}, + vapid::{self, repo::Provider as _}, }; pub struct Boot<'a> { @@ -26,6 +28,7 @@ impl<'a> Boot<'a> { let users = tx.users().all(resume_point).await?; let conversations = tx.conversations().all(resume_point).await?; let messages = tx.messages().all(resume_point).await?; + let vapid = tx.vapid().current().await.optional()?; tx.commit().await?; @@ -50,9 +53,16 @@ impl<'a> Boot<'a> { .filter(Sequence::up_to(resume_point)) .map(Event::from); + let vapid_events = vapid + .iter() + .flat_map(vapid::History::events) + .filter(Sequence::up_to(resume_point)) + .map(Event::from); + let events = user_events .merge_by(conversation_events, Sequence::merge) .merge_by(message_events, Sequence::merge) + .merge_by(vapid_events, Sequence::merge) .collect(); Ok(Snapshot { @@ -65,8 +75,9 @@ impl<'a> Boot<'a> { #[derive(Debug, thiserror::Error)] #[error(transparent)] pub enum Error { - Name(#[from] name::Error), Database(#[from] sqlx::Error), + Name(#[from] name::Error), + Ecdsa(#[from] p256::ecdsa::Error), } impl From<user::repo::LoadError> for Error { @@ -88,3 +99,13 @@ impl From<conversation::repo::LoadError> for Error { } } } + +impl From<vapid::repo::Error> for Error { + fn from(error: vapid::repo::Error) -> Self { + use vapid::repo::Error; + match error { + Error::Database(error) => error.into(), + Error::Ecdsa(error) => error.into(), + } + } +} diff --git a/src/boot/handlers/boot/test.rs b/src/boot/handlers/boot/test.rs index cb50442..3c09b0f 100644 --- a/src/boot/handlers/boot/test.rs +++ b/src/boot/handlers/boot/test.rs @@ -81,6 +81,74 @@ async fn includes_messages() { } #[tokio::test] +async fn includes_vapid_key() { + let app = fixtures::scratch_app().await; + + app.vapid() + .refresh_key(&fixtures::now()) + .await + .expect("key rotation always succeeds"); + + let viewer = fixtures::identity::fictitious(); + let response = super::handler(State(app), viewer) + .await + .expect("boot always succeeds"); + + response + .snapshot + .events + .into_iter() + .filter_map(fixtures::event::vapid) + .filter_map(fixtures::event::vapid::changed) + .exactly_one() + .expect("only one vapid key has been created"); +} + +#[tokio::test] +async fn includes_only_latest_vapid_key() { + let app = fixtures::scratch_app().await; + + app.vapid() + .refresh_key(&fixtures::ancient()) + .await + .expect("key rotation always succeeds"); + + let viewer = fixtures::identity::fictitious(); + let response = super::handler(State(app.clone()), viewer.clone()) + .await + .expect("boot always succeeds"); + + let original_key = response + .snapshot + .events + .into_iter() + .filter_map(fixtures::event::vapid) + .filter_map(fixtures::event::vapid::changed) + .exactly_one() + .expect("only one vapid key has been created"); + + app.vapid() + .refresh_key(&fixtures::now()) + .await + .expect("key rotation always succeeds"); + + let response = super::handler(State(app), viewer) + .await + .expect("boot always succeeds"); + + let rotated_key = response + .snapshot + .events + .into_iter() + .filter_map(fixtures::event::vapid) + .filter_map(fixtures::event::vapid::changed) + .exactly_one() + .expect("only one vapid key should be returned"); + + assert_ne!(original_key, rotated_key); +} + +#[tokio::test] async fn includes_expired_messages() { let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::ancient()).await; |
