use std::sync::Arc;
use torii::{SessionConfig, Torii};
use torii_core::repositories::RepositoryProvider;
use torii_core::session::{JwtConfig, SessionToken};
#[cfg(feature = "sqlite")]
use torii::sqlite::SqliteRepositoryProvider;
const TEST_HS256_SECRET: &[u8] = b"this_is_a_test_secret_key_for_hs256_jwt_tokens_not_for_prod";
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_register_user_with_password() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories));
let email = "test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
assert_eq!(user.email, email);
assert!(!user.is_email_verified());
torii.set_user_email_verified(&user.id).await.unwrap();
let user = torii.get_user(&user.id).await.unwrap().unwrap();
assert!(user.is_email_verified());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_login_with_password() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories));
let email = "test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
torii.set_user_email_verified(&user.id).await.unwrap();
let user_agent = Some("Test User Agent".to_string());
let ip_address = Some("127.0.0.1".to_string());
let (logged_in_user, session) = torii
.password()
.authenticate(email, password, user_agent.clone(), ip_address.clone())
.await
.unwrap();
assert_eq!(logged_in_user.id, user.id);
assert_eq!(logged_in_user.email, email);
assert_eq!(session.user_id, user.id);
assert_eq!(session.user_agent, user_agent);
assert_eq!(session.ip_address, ip_address);
assert!(!session.is_expired());
let result = torii
.password()
.authenticate(email, "wrong-password", None, None)
.await;
assert!(result.is_err());
let result = torii
.password()
.authenticate("nonexistent@example.com", password, None, None)
.await;
assert!(result.is_err());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_login_with_unverified_email() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories));
let email = "unverified@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
let result = torii
.password()
.authenticate(email, password, None, None)
.await;
assert!(result.is_ok());
let (logged_in_user, _session) = result.unwrap();
assert_eq!(logged_in_user.id, user.id);
assert!(!logged_in_user.is_email_verified());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_session_expiration() {
use chrono::Duration;
use std::time::Duration as StdDuration;
use tokio::time::sleep;
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories))
.with_session_config(SessionConfig::default().expires_in(Duration::seconds(1)));
let email = "test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
torii.set_user_email_verified(&user.id).await.unwrap();
let (_, session) = torii
.password()
.authenticate(email, password, None, None)
.await
.unwrap();
let retrieved = torii.get_session(&session.token).await.unwrap();
assert_eq!(retrieved.user_id, user.id);
sleep(StdDuration::from_secs(2)).await;
let result = torii.get_session(&session.token).await;
assert!(result.is_err());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_multiple_sessions() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories));
let email = "test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
torii.set_user_email_verified(&user.id).await.unwrap();
let (_, session1) = torii
.password()
.authenticate(
email,
password,
Some("Device 1".to_string()),
Some("127.0.0.1".to_string()),
)
.await
.unwrap();
let (_, session2) = torii
.password()
.authenticate(
email,
password,
Some("Device 2".to_string()),
Some("127.0.0.2".to_string()),
)
.await
.unwrap();
let retrieved1 = torii.get_session(&session1.token).await.unwrap();
let retrieved2 = torii.get_session(&session2.token).await.unwrap();
assert_eq!(retrieved1.user_id, user.id);
assert_eq!(retrieved2.user_id, user.id);
assert_eq!(retrieved1.user_agent, Some("Device 1".to_string()));
assert_eq!(retrieved2.user_agent, Some("Device 2".to_string()));
torii.delete_session(&session1.token).await.unwrap();
let result = torii.get_session(&session1.token).await;
assert!(result.is_err());
let retrieved2 = torii.get_session(&session2.token).await.unwrap();
assert_eq!(retrieved2.user_id, user.id);
torii.delete_sessions_for_user(&user.id).await.unwrap();
let result1 = torii.get_session(&session1.token).await;
let result2 = torii.get_session(&session2.token).await;
assert!(result1.is_err());
assert!(result2.is_err());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_password_auth_with_jwt() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let jwt_config = JwtConfig::new_hs256(TEST_HS256_SECRET.to_vec())
.with_issuer("torii-test-hs256")
.with_metadata(true);
let torii = Torii::new(Arc::new(repositories)).with_jwt_sessions(jwt_config);
let email = "test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
torii.set_user_email_verified(&user.id).await.unwrap();
let (logged_in_user, session) = torii
.password()
.authenticate(email, password, None, None)
.await
.unwrap();
assert_eq!(logged_in_user.id, user.id);
assert_eq!(logged_in_user.email, email);
match &session.token {
SessionToken::Jwt(_) => {
}
_ => panic!("Expected JWT token"),
}
let retrieved = torii.get_session(&session.token).await.unwrap();
assert_eq!(retrieved.user_id, user.id);
let result = torii
.password()
.authenticate(email, "wrong-password", None, None)
.await;
assert!(result.is_err());
}
#[cfg(all(feature = "password", feature = "sqlite"))]
#[tokio::test]
async fn test_delete_user() {
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
let repositories = SqliteRepositoryProvider::new(pool);
repositories.migrate().await.unwrap();
let torii = Torii::new(Arc::new(repositories));
let email = "delete-test@example.com";
let password = "password123";
let user = torii.password().register(email, password).await.unwrap();
torii.set_user_email_verified(&user.id).await.unwrap();
let session = torii.create_session(&user.id, None, None).await.unwrap();
let retrieved_user = torii.get_user(&user.id).await.unwrap();
assert!(retrieved_user.is_some(), "User should exist");
let retrieved_session = torii.get_session(&session.token).await;
assert!(retrieved_session.is_ok(), "Session should exist");
torii.delete_user(&user.id).await.unwrap();
let deleted_user = torii.get_user(&user.id).await.unwrap();
assert!(deleted_user.is_none(), "User should be deleted");
let deleted_session = torii.get_session(&session.token).await;
assert!(deleted_session.is_err(), "Session should be deleted");
}