Skip to main content

px_auth/infrastructure/
yaml_key_store.rs

1use crate::domain::key_store::{ApiKeyRecord, KeyStore};
2use async_trait::async_trait;
3use px_errors::AppError;
4use serde::Deserialize;
5use std::collections::HashMap;
6use std::path::Path;
7
8#[derive(Debug, Deserialize)]
9struct KeysFile {
10    keys: Vec<ApiKeyRecord>,
11}
12
13pub struct YamlKeyStore {
14    by_id: HashMap<String, ApiKeyRecord>,
15}
16
17impl YamlKeyStore {
18    pub async fn load(path: impl AsRef<Path>) -> Result<Self, AppError> {
19        let bytes = tokio::fs::read(path.as_ref())
20            .await
21            .map_err(|e| AppError::InternalError(format!("read keys yaml: {e}")))?;
22        let parsed: KeysFile = serde_yaml::from_slice(&bytes)
23            .map_err(|e| AppError::InternalError(format!("parse keys yaml: {e}")))?;
24        let mut by_id = HashMap::new();
25        for k in parsed.keys {
26            by_id.insert(k.id.clone(), k);
27        }
28        Ok(Self { by_id })
29    }
30
31    pub fn from_records(records: Vec<ApiKeyRecord>) -> Self {
32        let by_id = records.into_iter().map(|r| (r.id.clone(), r)).collect();
33        Self { by_id }
34    }
35}
36
37#[async_trait]
38impl KeyStore for YamlKeyStore {
39    async fn find_by_id(&self, id: &str) -> Result<Option<ApiKeyRecord>, AppError> {
40        Ok(self.by_id.get(id).cloned())
41    }
42
43    async fn list_ids(&self) -> Result<Vec<String>, AppError> {
44        Ok(self.by_id.keys().cloned().collect())
45    }
46}