use crate::db::repository::traits::RefreshTokensRepository; use async_trait::async_trait; use sqlx::PgPool; pub struct PostgresRefreshTokensRepository { pub pool: PgPool, } use crate::db::repository::sqlite::refresh_tokens::RefreshToken; #[async_trait] impl RefreshTokensRepository for PostgresRefreshTokensRepository { async fn create( &self, id: &str, user_id: &str, token_hash: &str, expires_at: &str, ) -> Result { sqlx::query_as::<_, RefreshToken>( r#" INSERT INTO refresh_tokens (id, user_id, token_hash, expires_at) VALUES ($1, $2, $3, $4) RETURNING * "#, ) .bind(id) .bind(user_id) .bind(token_hash) .bind(expires_at) .fetch_one(&self.pool) .await } async fn find_by_hash(&self, token_hash: &str) -> Result, sqlx::Error> { sqlx::query_as::<_, RefreshToken>( "SELECT * FROM refresh_tokens WHERE token_hash = $1 AND revoked = 0", ) .bind(token_hash) .fetch_optional(&self.pool) .await } async fn revoke(&self, id: &str) -> Result<(), sqlx::Error> { sqlx::query("UPDATE refresh_tokens SET revoked = 1 WHERE id = $1") .bind(id) .execute(&self.pool) .await?; Ok(()) } async fn revoke_all_for_user(&self, user_id: &str) -> Result<(), sqlx::Error> { sqlx::query("UPDATE refresh_tokens SET revoked = 1 WHERE user_id = $1") .bind(user_id) .execute(&self.pool) .await?; Ok(()) } }