//! Guest session database queries. use chrono::{DateTime, TimeDelta, Utc}; use sqlx::PgPool; use uuid::Uuid; use chattyness_error::AppError; /// Guest session record. #[derive(Debug, Clone)] #[cfg_attr(feature = "ssr", derive(sqlx::FromRow))] pub struct GuestSession { pub id: Uuid, pub guest_name: String, pub current_realm_id: Option, pub expires_at: DateTime, pub created_at: DateTime, } /// Create a new guest session. /// /// Returns the guest session ID. pub async fn create_guest_session( pool: &PgPool, guest_name: &str, realm_id: Uuid, token_hash: &str, user_agent: Option<&str>, ip_address: Option<&str>, expires_at: DateTime, ) -> Result { let (session_id,): (Uuid,) = sqlx::query_as( r#" INSERT INTO auth.guest_sessions (guest_name, token_hash, user_agent, ip_address, current_realm_id, expires_at) VALUES ($1, $2, $3, $4::inet, $5, $6) RETURNING id "#, ) .bind(guest_name) .bind(token_hash) .bind(user_agent) .bind(ip_address) .bind(realm_id) .bind(expires_at) .fetch_one(pool) .await?; Ok(session_id) } /// Get a guest session by ID. pub async fn get_guest_session( pool: &PgPool, session_id: Uuid, ) -> Result, AppError> { let session = sqlx::query_as::<_, GuestSession>( r#" SELECT id, guest_name, current_realm_id, expires_at, created_at FROM auth.guest_sessions WHERE id = $1 AND expires_at > now() "#, ) .bind(session_id) .fetch_optional(pool) .await?; // Update last activity if session exists if session.is_some() { sqlx::query("UPDATE auth.guest_sessions SET last_activity_at = now() WHERE id = $1") .bind(session_id) .execute(pool) .await?; } Ok(session) } /// Delete a guest session. pub async fn delete_guest_session(pool: &PgPool, session_id: Uuid) -> Result<(), AppError> { sqlx::query("DELETE FROM auth.guest_sessions WHERE id = $1") .bind(session_id) .execute(pool) .await?; Ok(()) } /// Generate a random guest name like "Guest_12345". pub fn generate_guest_name() -> String { use rand::Rng; let mut rng = rand::thread_rng(); let number: u32 = rng.gen_range(10000..100000); format!("Guest_{}", number) } /// Calculate guest session expiry (24 hours from now). pub fn guest_session_expiry() -> DateTime { Utc::now() + TimeDelta::hours(24) }