Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates for async-sessions-v4 #298

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aws-lambda-example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ trillium-sessions = { path = "../sessions" }
trillium-askama = { path = "../askama" }
futures-lite = "1.12.0"
askama = "0.12.0"
async-session-cookie-store = { git = "https://github.com/http-rs/async-session", branch = "overhaul-session-and-session-store" }
3 changes: 2 additions & 1 deletion aws-lambda-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use askama::Template;
use async_session_cookie_store::CookieStore;
use trillium::Conn;
use trillium_askama::AskamaConnExt;
use trillium_aws_lambda::LambdaConnExt;
use trillium_cookies::CookiesHandler;
use trillium_logger::Logger;
use trillium_router::{Router, RouterConnExt};
use trillium_sessions::{CookieStore, SessionConnExt, SessionHandler};
use trillium_sessions::{SessionConnExt, SessionHandler};

#[derive(Template)]
#[template(path = "hello.html")]
Expand Down
1 change: 1 addition & 0 deletions example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ trillium-method-override = { path = "../method-override" }
trillium-conn-id = { path = "../conn-id" }
trillium-caching-headers = { path = "../caching-headers" }
trillium-compression = { path = "../compression" }
async-session-memory-store = { git = "https://github.com/http-rs/async-session", branch = "overhaul-session-and-session-store" }

[dev-dependencies]
trillium-testing = { path = "../testing" }
3 changes: 2 additions & 1 deletion example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use askama::Template;
use async_session_memory_store::MemoryStore;
use futures_lite::prelude::*;
use std::time::Duration;
use trillium::{Conn, Handler};
Expand All @@ -11,7 +12,7 @@ use trillium_conn_id::log_formatter::conn_id;
use trillium_logger::apache_common;
use trillium_router::{Router, RouterConnExt};
use trillium_rustls::RustlsConnector;
use trillium_sessions::{MemoryStore, SessionConnExt};
use trillium_sessions::SessionConnExt;
use trillium_smol::TcpConnector;
use trillium_static_compiled::static_compiled;
use trillium_websockets::{Message, WebSocket, WebSocketConn};
Expand Down
9 changes: 7 additions & 2 deletions sessions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ categories = ["web-programming::http-server", "web-programming"]

[dependencies]
trillium-cookies = { path = "../cookies", version = "^0.4.0" }
trillium = { path = "../trillium", version = "^0.2.0"}
async-session = "3.0.0"
trillium = { path = "../trillium", version = "^0.2.0" }
async-session = { git = "https://github.com/http-rs/async-session", branch = "overhaul-session-and-session-store" }
log = "0.4.17"
hmac = { version = "0.12.1", features = ["std"] }
sha2 = "0.10.6"
base64 = "0.21.0"
serde = "1.0.159"

[dev-dependencies]
env_logger = "0.10.0"
trillium-smol = { path = "../smol" }
trillium-testing = { path = "../testing" }
async-session-memory-store = { git = "https://github.com/http-rs/async-session", branch = "overhaul-session-and-session-store" }

[package.metadata.cargo-udeps.ignore]
development = ["trillium-testing"]
3 changes: 2 additions & 1 deletion sessions/examples/sessions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use async_session_memory_store::MemoryStore;
use trillium::Conn;
use trillium_cookies::CookiesHandler;
use trillium_sessions::{MemoryStore, SessionConnExt, SessionHandler};
use trillium_sessions::{SessionConnExt, SessionHandler};

pub fn main() {
env_logger::init();
Expand Down
6 changes: 4 additions & 2 deletions sessions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ store if it requires it
```
use trillium::Conn;
use trillium_cookies::{CookiesHandler, cookie::Cookie};
use trillium_sessions::{MemoryStore, SessionConnExt, SessionHandler};
use trillium_sessions::{SessionConnExt, SessionHandler};
use async_session_memory_store::MemoryStore;

# std::env::set_var("TRILLIUM_SESSION_SECRET", "this is just for testing and you should not do this");
let session_secret = std::env::var("TRILLIUM_SESSION_SECRET").unwrap();

Expand Down Expand Up @@ -119,4 +121,4 @@ pub use session_conn_ext::SessionConnExt;
mod session_handler;
pub use session_handler::{sessions, SessionHandler};

pub use async_session::{CookieStore, MemoryStore, Session};
pub use async_session::{Session, SessionStore};
3 changes: 2 additions & 1 deletion sessions/src/session_conn_ext.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use async_session::{serde::Serialize, Session};
use async_session::Session;
use serde::Serialize;
use trillium::Conn;

/**
Expand Down
52 changes: 27 additions & 25 deletions sessions/src/session_handler.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
const BASE64_DIGEST_LEN: usize = 44;
use async_session::{
base64,
hmac::{Hmac, Mac, NewMac},
sha2::Sha256,
Session, SessionStore,
};
use async_session::{Session, SessionStore};
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
use hmac::{digest::generic_array::GenericArray, Hmac, Mac};
use sha2::Sha256;
use std::{
fmt::{self, Debug, Formatter},
iter,
Expand Down Expand Up @@ -35,7 +33,10 @@ pub struct SessionHandler<Store> {
older_keys: Vec<Key>,
}

impl<Store: SessionStore> Debug for SessionHandler<Store> {
impl<Store> Debug for SessionHandler<Store>
where
Store: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("SessionHandler")
.field("store", &self.store)
Expand All @@ -51,7 +52,10 @@ impl<Store: SessionStore> Debug for SessionHandler<Store> {
}
}

impl<Store: SessionStore> SessionHandler<Store> {
impl<Store> SessionHandler<Store>
where
Store: SessionStore + Send + Sync + 'static,
{
/**
Constructs a SessionHandler from the given
[`async_session::SessionStore`] and secret. The `secret` MUST be
Expand Down Expand Up @@ -82,7 +86,8 @@ impl<Store: SessionStore> SessionHandler<Store> {

```rust
# use std::time::Duration;
# use trillium_sessions::{SessionHandler, MemoryStore};
# use trillium_sessions::SessionHandler;
# use async_session_memory_store::MemoryStore;
# use trillium_cookies::{CookiesHandler, cookie::SameSite};
# std::env::set_var("TRILLIUM_SESSION_SECRETS", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
// this logic will be unique to your deployment
Expand Down Expand Up @@ -187,12 +192,7 @@ impl<Store: SessionStore> SessionHandler<Store> {

async fn load_or_create(&self, cookie_value: Option<&str>) -> Session {
let session = match cookie_value {
Some(cookie_value) => self
.store
.load_session(String::from(cookie_value))
.await
.ok()
.flatten(),
Some(cookie_value) => self.store.load_session(cookie_value).await.ok().flatten(),
None => None,
};

Expand Down Expand Up @@ -230,7 +230,7 @@ impl<Store: SessionStore> SessionHandler<Store> {
mac.update(cookie.value().as_bytes());

// Cookie's new value is [MAC | original-value].
let mut new_value = base64::encode(mac.finalize().into_bytes());
let mut new_value = BASE64.encode(mac.finalize().into_bytes());
new_value.push_str(cookie.value());
cookie.set_value(new_value);
}
Expand All @@ -248,7 +248,7 @@ impl<Store: SessionStore> SessionHandler<Store> {

// Split [MAC | original-value] into its two parts.
let (digest_str, value) = cookie_value.split_at(BASE64_DIGEST_LEN);
let digest = match base64::decode(digest_str) {
let digest = match BASE64.decode(digest_str) {
Ok(digest) => digest,
Err(_) => {
log::trace!("bad base64 digest");
Expand All @@ -261,14 +261,17 @@ impl<Store: SessionStore> SessionHandler<Store> {
.find_map(|key| {
let mut mac = Hmac::<Sha256>::new_from_slice(key.signing()).expect("good key");
mac.update(value.as_bytes());
mac.verify(&digest).ok()
mac.verify(GenericArray::from_slice(&digest)).ok()
})
.map(|_| value)
}
}

#[async_trait]
impl<Store: SessionStore> Handler for SessionHandler<Store> {
impl<Store> Handler for SessionHandler<Store>
where
Store: SessionStore + Send + Sync + 'static,
{
async fn run(&self, mut conn: Conn) -> Conn {
let session = conn.take_state::<Session>();

Expand All @@ -290,20 +293,19 @@ impl<Store: SessionStore> Handler for SessionHandler<Store> {
}

async fn before_send(&self, mut conn: Conn) -> Conn {
if let Some(session) = conn.take_state::<Session>() {
let session_to_keep = session.clone();
if let Some(mut session) = conn.take_state::<Session>() {
let secure = conn.is_secure();
if session.is_destroyed() {
self.store.destroy_session(session).await.ok();
self.store.destroy_session(&mut session).await.ok();
conn.cookies_mut()
.remove(Cookie::named(self.cookie_name.clone()));
} else if self.save_unchanged || session.data_changed() {
if let Ok(Some(cookie_value)) = self.store.store_session(session).await {
if let Ok(Some(cookie_value)) = self.store.store_session(&mut session).await {
conn.cookies_mut()
.add(self.build_cookie(secure, cookie_value));
}
}
conn.with_state(session_to_keep)
conn.with_state(session)
} else {
conn
}
Expand All @@ -313,7 +315,7 @@ impl<Store: SessionStore> Handler for SessionHandler<Store> {
/// Alias for [`SessionHandler::new`]
pub fn sessions<Store>(store: Store, secret: impl AsRef<[u8]>) -> SessionHandler<Store>
where
Store: SessionStore,
Store: SessionStore + Send + Sync + 'static,
{
SessionHandler::new(store, secret)
}