Spaces:
Running
Running
| use crate::domain::error::AppResult; | |
| use crate::infrastructure::db::DbPool; | |
| use serde::{Deserialize, Serialize}; | |
| use sqlx::FromRow; | |
| pub struct ApiKeyRecord { | |
| pub key_id: String, | |
| pub merchant_id: String, | |
| pub name: String, | |
| pub secret_hash: String, | |
| pub scopes: serde_json::Value, | |
| pub last_used_at: Option<chrono::NaiveDateTime>, | |
| pub created_at: chrono::NaiveDateTime, | |
| } | |
| impl ApiKeyRecord { | |
| pub async fn find_by_id(pool: &DbPool, key_id: &str) -> AppResult<Option<Self>> { | |
| let record = sqlx::query_as::<_, Self>("SELECT * FROM api_keys WHERE key_id = $1") | |
| .bind(key_id) | |
| .fetch_optional(pool) | |
| .await?; | |
| Ok(record) | |
| } | |
| pub async fn create(pool: &DbPool, record: &Self) -> AppResult<()> { | |
| sqlx::query( | |
| "INSERT INTO api_keys (key_id, merchant_id, name, secret_hash, scopes) VALUES ($1, $2, $3, $4, $5)" | |
| ) | |
| .bind(&record.key_id) | |
| .bind(&record.merchant_id) | |
| .bind(&record.name) | |
| .bind(&record.secret_hash) | |
| .bind(&record.scopes) | |
| .execute(pool) | |
| .await?; | |
| Ok(()) | |
| } | |
| pub async fn delete(pool: &DbPool, key_id: &str, merchant_id: &str) -> AppResult<()> { | |
| sqlx::query("DELETE FROM api_keys WHERE key_id = $1 AND merchant_id = $2") | |
| .bind(key_id) | |
| .bind(merchant_id) | |
| .execute(pool) | |
| .await?; | |
| Ok(()) | |
| } | |
| pub async fn list_for_merchant(pool: &DbPool, merchant_id: &str) -> AppResult<Vec<Self>> { | |
| let records = sqlx::query_as::<_, Self>( | |
| "SELECT * FROM api_keys WHERE merchant_id = $1 ORDER BY created_at DESC", | |
| ) | |
| .bind(merchant_id) | |
| .fetch_all(pool) | |
| .await?; | |
| Ok(records) | |
| } | |
| } | |