From d3be5e3682c8d63575cc9f630041417ba20e70f4 Mon Sep 17 00:00:00 2001 From: Karuna Murti Date: Mon, 2 Sep 2024 23:20:34 +0900 Subject: [PATCH] Make chrono work (#46) --- sqlx-store/Cargo.toml | 15 ++++++++++----- sqlx-store/src/lib.rs | 28 ++++++++++++++++++++++++++++ sqlx-store/src/mysql_store.rs | 7 +++---- sqlx-store/src/postgres_store.rs | 10 +++++----- sqlx-store/src/sqlite_store.rs | 7 +++---- tests/Cargo.toml | 1 + 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/sqlx-store/Cargo.toml b/sqlx-store/Cargo.toml index afd89d4..c2f68a2 100644 --- a/sqlx-store/Cargo.toml +++ b/sqlx-store/Cargo.toml @@ -13,16 +13,21 @@ documentation = "https://docs.rs/tower-sessions-sqlx-store" readme = "README.md" [features] +default = ["time"] sqlite = ["sqlx/sqlite"] postgres = ["sqlx/postgres"] mysql = ["sqlx/mysql"] +time = ["sqlx/time", "dep:time"] +chrono = ["sqlx/chrono", "dep:chrono"] + [dependencies] async-trait = "0.1.77" rmp-serde = "1.1.2" -sqlx = { version = "0.8.0", features = ["time", "runtime-tokio"] } +sqlx = { version = "0.8.0", features = ["runtime-tokio"] } thiserror = "1.0.56" -time = "0.3.31" +time = { version = "0.3.31", optional = true } +chrono = { version = "0.4.38", optional = true } tower-sessions-core = { version = "0.12.1", features = ["deletion-task"] } [dev-dependencies] @@ -34,12 +39,12 @@ serde = "1" [[example]] name = "sqlite" -required-features = ["sqlite"] +required-features = ["sqlite", "time"] [[example]] name = "postgres" -required-features = ["postgres"] +required-features = ["postgres", "time"] [[example]] name = "mysql" -required-features = ["mysql"] +required-features = ["mysql", "time"] diff --git a/sqlx-store/src/lib.rs b/sqlx-store/src/lib.rs index b9c6382..679a867 100644 --- a/sqlx-store/src/lib.rs +++ b/sqlx-store/src/lib.rs @@ -1,6 +1,12 @@ pub use sqlx; use tower_sessions_core::session_store; +#[cfg(any( + all(feature = "time", feature = "chrono"), + all(not(feature = "time"), not(feature = "chrono")) +))] +compile_error!("Exactly one of `time` and `chrono` features must be enabled. This is due to a change in sqlx where chrono types can only be enabled if time is disabled."); + #[cfg(feature = "mysql")] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] pub use self::mysql_store::MySqlStore; @@ -48,3 +54,25 @@ impl From for session_store::Error { } } } + +#[cfg(feature = "time")] +pub fn current_time() -> time::OffsetDateTime { + time::OffsetDateTime::now_utc() +} + +#[cfg(feature = "chrono")] +pub fn current_time() -> chrono::DateTime { + chrono::Utc::now() +} + +#[cfg(feature = "time")] +pub fn convert_expiry_date(expiry_date: time::OffsetDateTime) -> time::OffsetDateTime { + expiry_date +} + +#[cfg(feature = "chrono")] +pub fn convert_expiry_date(expiry_date: time::OffsetDateTime) -> chrono::DateTime { + // if we can't convert the expiry date to a chrono type, return the current time i.e. effectively assume our session has expired + chrono::DateTime::from_timestamp(expiry_date.unix_timestamp(), expiry_date.nanosecond()) + .unwrap_or(chrono::Utc::now()) +} diff --git a/sqlx-store/src/mysql_store.rs b/sqlx-store/src/mysql_store.rs index 5afbf44..861e4fe 100644 --- a/sqlx-store/src/mysql_store.rs +++ b/sqlx-store/src/mysql_store.rs @@ -1,12 +1,11 @@ use async_trait::async_trait; use sqlx::{MySqlConnection, MySqlPool}; -use time::OffsetDateTime; use tower_sessions_core::{ session::{Id, Record}, session_store, ExpiredDeletion, SessionStore, }; -use crate::SqlxStoreError; +use crate::{convert_expiry_date, current_time, SqlxStoreError}; /// A MySQL session store. #[derive(Clone, Debug)] @@ -147,7 +146,7 @@ impl MySqlStore { sqlx::query(&query) .bind(record.id.to_string()) .bind(rmp_serde::to_vec(&record).map_err(SqlxStoreError::Encode)?) - .bind(record.expiry_date) + .bind(convert_expiry_date(record.expiry_date)) .execute(conn) .await .map_err(SqlxStoreError::Sqlx)?; @@ -205,7 +204,7 @@ impl SessionStore for MySqlStore { ); let data: Option<(Vec,)> = sqlx::query_as(&query) .bind(session_id.to_string()) - .bind(OffsetDateTime::now_utc()) + .bind(current_time()) .fetch_optional(&self.pool) .await .map_err(SqlxStoreError::Sqlx)?; diff --git a/sqlx-store/src/postgres_store.rs b/sqlx-store/src/postgres_store.rs index 26fc9ad..641a12a 100644 --- a/sqlx-store/src/postgres_store.rs +++ b/sqlx-store/src/postgres_store.rs @@ -1,13 +1,11 @@ +use crate::{convert_expiry_date, current_time, SqlxStoreError}; use async_trait::async_trait; use sqlx::{PgConnection, PgPool}; -use time::OffsetDateTime; use tower_sessions_core::{ session::{Id, Record}, session_store, ExpiredDeletion, SessionStore, }; -use crate::SqlxStoreError; - /// A PostgreSQL session store. #[derive(Clone, Debug)] pub struct PostgresStore { @@ -157,10 +155,11 @@ impl PostgresStore { schema_name = self.schema_name, table_name = self.table_name ); + sqlx::query(&query) .bind(record.id.to_string()) .bind(rmp_serde::to_vec(&record).map_err(SqlxStoreError::Encode)?) - .bind(record.expiry_date) + .bind(convert_expiry_date(record.expiry_date)) .execute(conn) .await .map_err(SqlxStoreError::Sqlx)?; @@ -217,9 +216,10 @@ impl SessionStore for PostgresStore { schema_name = self.schema_name, table_name = self.table_name ); + let record_value: Option<(Vec,)> = sqlx::query_as(&query) .bind(session_id.to_string()) - .bind(OffsetDateTime::now_utc()) + .bind(current_time()) .fetch_optional(&self.pool) .await .map_err(SqlxStoreError::Sqlx)?; diff --git a/sqlx-store/src/sqlite_store.rs b/sqlx-store/src/sqlite_store.rs index 996ba43..7276c1c 100644 --- a/sqlx-store/src/sqlite_store.rs +++ b/sqlx-store/src/sqlite_store.rs @@ -1,13 +1,12 @@ use async_trait::async_trait; use sqlx::{sqlite::SqlitePool, SqliteConnection}; -use time::OffsetDateTime; use tower_sessions_core::{ session::{Id, Record}, session_store::{self, ExpiredDeletion}, SessionStore, }; -use crate::SqlxStoreError; +use crate::{convert_expiry_date, current_time, SqlxStoreError}; /// A SQLite session store. #[derive(Clone, Debug)] @@ -101,7 +100,7 @@ impl SqliteStore { sqlx::query(&query) .bind(record.id.to_string()) .bind(rmp_serde::to_vec(record).map_err(SqlxStoreError::Encode)?) - .bind(record.expiry_date) + .bind(convert_expiry_date(record.expiry_date)) .execute(conn) .await .map_err(SqlxStoreError::Sqlx)?; @@ -158,7 +157,7 @@ impl SessionStore for SqliteStore { ); let data: Option<(Vec,)> = sqlx::query_as(&query) .bind(session_id.to_string()) - .bind(OffsetDateTime::now_utc()) + .bind(current_time()) .fetch_optional(&self.pool) .await .map_err(SqlxStoreError::Sqlx)?; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 4e3c7e4..60bf169 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -18,6 +18,7 @@ tower-sessions-sqlx-store = { path = "../sqlx-store/", features = [ "sqlite", "mysql", "postgres", + "time", ] } tower-sessions-redis-store = { path = "../redis-store/" } tower-sessions-mongodb-store = { path = "../mongodb-store/" }