use chrono::{DateTime, Utc}; use sqlx::PgPool; use uuid::Uuid; #[derive(Debug, sqlx::FromRow)] pub struct Session { pub id: Uuid, pub user_id: Uuid, pub token_hash: String, pub expires_at: DateTime, pub last_seen_at: DateTime, pub created_at: DateTime, } impl Session { pub async fn create( pool: &PgPool, user_id: Uuid, token_hash: &str, expires_at: DateTime, ) -> Result { sqlx::query_as::<_, Self>( "INSERT INTO session (user_id, token_hash, expires_at) VALUES ($1, $2, $3) RETURNING *", ) .bind(user_id) .bind(token_hash) .bind(expires_at) .fetch_one(pool) .await } pub async fn find_by_token_hash( pool: &PgPool, token_hash: &str, ) -> Result, sqlx::Error> { sqlx::query_as::<_, Self>( "SELECT * FROM session WHERE token_hash = $1 AND expires_at > NOW()", ) .bind(token_hash) .fetch_optional(pool) .await } pub async fn touch(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { sqlx::query("UPDATE session SET last_seen_at = NOW() WHERE id = $1") .bind(id) .execute(pool) .await?; Ok(()) } pub async fn delete_by_token_hash( pool: &PgPool, token_hash: &str, ) -> Result<(), sqlx::Error> { sqlx::query("DELETE FROM session WHERE token_hash = $1") .bind(token_hash) .execute(pool) .await?; Ok(()) } }