Skip to main content

bindizr_db/repository/postgres/
api_token_repository_impl.rs

1use async_trait::async_trait;
2use sqlx::{Pool, Postgres, Row};
3
4use crate::{error::DatabaseError, model::api_token::ApiToken, repository::ApiTokenRepository};
5
6pub struct PostgresApiTokenRepository {
7    pool: Pool<Postgres>,
8}
9
10impl PostgresApiTokenRepository {
11    pub fn new(pool: Pool<Postgres>) -> Self {
12        Self { pool }
13    }
14}
15
16#[async_trait]
17impl ApiTokenRepository for PostgresApiTokenRepository {
18    async fn create(&self, mut token: ApiToken) -> Result<ApiToken, DatabaseError> {
19        let mut conn = self.pool.acquire().await?;
20
21        let result = sqlx::query(
22            r#"
23            INSERT INTO api_tokens (token, description, expires_at)
24            VALUES ($1, $2, $3)
25            RETURNING id
26        "#,
27        )
28        .bind(&token.token)
29        .bind(&token.description)
30        .bind(token.expires_at)
31        .fetch_one(&mut *conn)
32        .await?;
33
34        token.id = result.get::<i32, _>(0);
35
36        Ok(token)
37    }
38
39    async fn get_by_id(&self, id: i32) -> Result<Option<ApiToken>, DatabaseError> {
40        let mut conn = self.pool.acquire().await?;
41
42        let row = sqlx::query_as::<_, ApiToken>(
43            "SELECT id, token, description, expires_at, created_at, last_used_at FROM api_tokens WHERE id = $1"
44        )
45        .bind(id)
46        .fetch_optional(&mut *conn)
47        .await
48        ?;
49
50        Ok(row)
51    }
52
53    async fn get_by_token(&self, token: &str) -> Result<Option<ApiToken>, DatabaseError> {
54        let mut conn = self.pool.acquire().await?;
55
56        let row = sqlx::query_as::<_, ApiToken>(
57            "SELECT id, token, description, expires_at, created_at, last_used_at FROM api_tokens WHERE token = $1"
58        )
59        .bind(token)
60        .fetch_optional(&mut *conn)
61        .await
62        ?;
63
64        Ok(row)
65    }
66
67    async fn get_all(&self) -> Result<Vec<ApiToken>, DatabaseError> {
68        let mut conn = self.pool.acquire().await?;
69
70        let rows = sqlx::query_as::<_, ApiToken>(
71            "SELECT id, token, description, expires_at, created_at, last_used_at FROM api_tokens ORDER BY created_at DESC"
72        )
73        .fetch_all(&mut *conn)
74        .await
75        ?;
76
77        Ok(rows)
78    }
79
80    async fn update(&self, token: ApiToken) -> Result<ApiToken, DatabaseError> {
81        let mut conn = self.pool.acquire().await?;
82
83        sqlx::query(
84            r#"
85            UPDATE api_tokens 
86            SET description = $1, expires_at = $2, last_used_at = $3
87            WHERE id = $4
88        "#,
89        )
90        .bind(&token.description)
91        .bind(token.expires_at)
92        .bind(token.last_used_at)
93        .bind(token.id)
94        .execute(&mut *conn)
95        .await?;
96
97        Ok(token)
98    }
99
100    async fn delete(&self, id: i32) -> Result<(), DatabaseError> {
101        let mut conn = self.pool.acquire().await?;
102
103        sqlx::query("DELETE FROM api_tokens WHERE id = $1")
104            .bind(id)
105            .execute(&mut *conn)
106            .await?;
107
108        Ok(())
109    }
110}