Skip to main content

systemprompt_users/repository/banned_ip/
listing.rs

1//! Banned-IP listing queries.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use crate::error::Result;
7
8use super::BannedIpRepository;
9use super::types::BannedIp;
10
11impl BannedIpRepository {
12    pub async fn list_active_bans(&self, limit: i64) -> Result<Vec<BannedIp>> {
13        let bans = sqlx::query_as!(
14            BannedIp,
15            r#"
16            SELECT
17                ip_address,
18                reason,
19                banned_at,
20                expires_at,
21                ban_count,
22                last_offense_path,
23                last_user_agent,
24                is_permanent,
25                source_fingerprint,
26                ban_source,
27                associated_session_ids
28            FROM banned_ips
29            WHERE expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP
30            ORDER BY banned_at DESC
31            LIMIT $1
32            "#,
33            limit
34        )
35        .fetch_all(&*self.pool)
36        .await?;
37
38        Ok(bans)
39    }
40
41    pub async fn list_bans_by_source(&self, ban_source: &str, limit: i64) -> Result<Vec<BannedIp>> {
42        let bans = sqlx::query_as!(
43            BannedIp,
44            r#"
45            SELECT
46                ip_address,
47                reason,
48                banned_at,
49                expires_at,
50                ban_count,
51                last_offense_path,
52                last_user_agent,
53                is_permanent,
54                source_fingerprint,
55                ban_source,
56                associated_session_ids
57            FROM banned_ips
58            WHERE ban_source = $1
59              AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
60            ORDER BY banned_at DESC
61            LIMIT $2
62            "#,
63            ban_source,
64            limit
65        )
66        .fetch_all(&*self.pool)
67        .await?;
68
69        Ok(bans)
70    }
71
72    pub async fn list_bans_by_fingerprint(&self, fingerprint: &str) -> Result<Vec<BannedIp>> {
73        let bans = sqlx::query_as!(
74            BannedIp,
75            r#"
76            SELECT
77                ip_address,
78                reason,
79                banned_at,
80                expires_at,
81                ban_count,
82                last_offense_path,
83                last_user_agent,
84                is_permanent,
85                source_fingerprint,
86                ban_source,
87                associated_session_ids
88            FROM banned_ips
89            WHERE source_fingerprint = $1
90            ORDER BY banned_at DESC
91            "#,
92            fingerprint
93        )
94        .fetch_all(&*self.pool)
95        .await?;
96
97        Ok(bans)
98    }
99
100    pub async fn count_active_bans(&self) -> Result<i64> {
101        let result = sqlx::query_scalar!(
102            r#"
103            SELECT COUNT(*)::BIGINT as "count!"
104            FROM banned_ips
105            WHERE expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP
106            "#
107        )
108        .fetch_one(&*self.pool)
109        .await?;
110
111        Ok(result)
112    }
113}