Skip to main content

systemprompt_users/repository/session/
fingerprint.rs

1//! Fingerprint session lookups.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use super::SessionRepository;
7use crate::Result;
8use systemprompt_identifiers::SessionId;
9
10impl SessionRepository {
11    pub async fn fingerprint_session_ids(
12        &self,
13        fingerprint: &str,
14        window_days: i64,
15    ) -> Result<Vec<SessionId>> {
16        let window_days = i32::try_from(window_days).unwrap_or(i32::MAX);
17        Ok(sqlx::query_scalar!(
18            r#"
19            SELECT session_id as "session_id!: SessionId"
20            FROM user_sessions
21            WHERE fingerprint_hash = $1
22              AND started_at > CURRENT_TIMESTAMP - make_interval(days => $2)
23            "#,
24            fingerprint,
25            window_days,
26        )
27        .fetch_all(&*self.write_pool)
28        .await?)
29    }
30    pub async fn count_active_fingerprint(&self, fingerprint_hash: &str) -> Result<i32> {
31        let row = sqlx::query_scalar!(
32            r#"
33            SELECT COUNT(*)::INT as "count!"
34            FROM user_sessions
35            WHERE fingerprint_hash = $1
36              AND ended_at IS NULL
37              AND last_activity_at > CURRENT_TIMESTAMP - INTERVAL '7 days'
38            "#,
39            fingerprint_hash,
40        )
41        .fetch_one(&*self.write_pool)
42        .await?;
43
44        Ok(row)
45    }
46    pub async fn find_reusable_fingerprint(
47        &self,
48        fingerprint_hash: &str,
49    ) -> Result<Option<SessionId>> {
50        let row = sqlx::query_scalar!(
51            r#"
52            SELECT session_id as "session_id!: SessionId"
53            FROM user_sessions
54            WHERE fingerprint_hash = $1
55              AND ended_at IS NULL
56              AND last_activity_at > CURRENT_TIMESTAMP - INTERVAL '7 days'
57            ORDER BY last_activity_at ASC
58            LIMIT 1
59            "#,
60            fingerprint_hash,
61        )
62        .fetch_optional(&*self.write_pool)
63        .await?;
64
65        Ok(row)
66    }
67}