Skip to main content

rs_auth_postgres/
verification.rs

1use async_trait::async_trait;
2use sqlx::Row;
3
4use rs_auth_core::error::AuthError;
5use rs_auth_core::store::VerificationStore;
6use rs_auth_core::types::{NewVerification, Verification};
7
8use crate::db::AuthDb;
9
10#[async_trait]
11impl VerificationStore for AuthDb {
12    async fn create_verification(
13        &self,
14        verification: NewVerification,
15    ) -> Result<Verification, AuthError> {
16        sqlx::query(
17            r#"
18            INSERT INTO verifications (identifier, token_hash, expires_at)
19            VALUES ($1, $2, $3)
20            RETURNING id, identifier, token_hash, expires_at, created_at, updated_at
21            "#,
22        )
23        .bind(verification.identifier)
24        .bind(verification.token_hash)
25        .bind(verification.expires_at)
26        .fetch_one(&self.pool)
27        .await
28        .map(|row| Verification {
29            id: row.get("id"),
30            identifier: row.get("identifier"),
31            token_hash: row.get("token_hash"),
32            expires_at: row.get("expires_at"),
33            created_at: row.get("created_at"),
34            updated_at: row.get("updated_at"),
35        })
36        .map_err(|error| AuthError::Store(error.to_string()))
37    }
38
39    async fn find_by_identifier(
40        &self,
41        identifier: &str,
42    ) -> Result<Option<Verification>, AuthError> {
43        sqlx::query(
44            r#"
45            SELECT id, identifier, token_hash, expires_at, created_at, updated_at
46            FROM verifications
47            WHERE identifier = $1
48            "#,
49        )
50        .bind(identifier)
51        .fetch_optional(&self.pool)
52        .await
53        .map(|row| {
54            row.map(|row| Verification {
55                id: row.get("id"),
56                identifier: row.get("identifier"),
57                token_hash: row.get("token_hash"),
58                expires_at: row.get("expires_at"),
59                created_at: row.get("created_at"),
60                updated_at: row.get("updated_at"),
61            })
62        })
63        .map_err(|error| AuthError::Store(error.to_string()))
64    }
65
66    async fn find_by_token_hash(
67        &self,
68        token_hash: &str,
69    ) -> Result<Option<Verification>, AuthError> {
70        sqlx::query(
71            r#"
72            SELECT id, identifier, token_hash, expires_at, created_at, updated_at
73            FROM verifications
74            WHERE token_hash = $1
75            "#,
76        )
77        .bind(token_hash)
78        .fetch_optional(&self.pool)
79        .await
80        .map(|row| {
81            row.map(|row| Verification {
82                id: row.get("id"),
83                identifier: row.get("identifier"),
84                token_hash: row.get("token_hash"),
85                expires_at: row.get("expires_at"),
86                created_at: row.get("created_at"),
87                updated_at: row.get("updated_at"),
88            })
89        })
90        .map_err(|error| AuthError::Store(error.to_string()))
91    }
92
93    async fn delete_verification(&self, id: i64) -> Result<(), AuthError> {
94        sqlx::query(r#"DELETE FROM verifications WHERE id = $1"#)
95            .bind(id)
96            .execute(&self.pool)
97            .await
98            .map(|_| ())
99            .map_err(|error| AuthError::Store(error.to_string()))
100    }
101
102    async fn delete_by_identifier(&self, identifier: &str) -> Result<(), AuthError> {
103        sqlx::query(r#"DELETE FROM verifications WHERE identifier = $1"#)
104            .bind(identifier)
105            .execute(&self.pool)
106            .await
107            .map(|_| ())
108            .map_err(|error| AuthError::Store(error.to_string()))
109    }
110
111    async fn delete_expired(&self) -> Result<u64, AuthError> {
112        sqlx::query(r#"DELETE FROM verifications WHERE expires_at < now()"#)
113            .execute(&self.pool)
114            .await
115            .map(|result| result.rows_affected())
116            .map_err(|error| AuthError::Store(error.to_string()))
117    }
118}