fuel-web-utils 0.0.27

Fuel library for web utils
use dashmap::DashMap;

use super::{ApiKey, ApiKeyError};

#[derive(Debug, Default)]
pub struct InMemoryApiKeyStorage {
    map: DashMap<String, ApiKey>,
}

impl InMemoryApiKeyStorage {
    pub fn new() -> Self {
        Self {
            map: DashMap::new(),
        }
    }
}

impl Clone for InMemoryApiKeyStorage {
    fn clone(&self) -> Self {
        Self {
            map: self.map.clone(),
        }
    }
}

#[derive(Debug, thiserror::Error)]
pub enum ApiKeyStorageError {
    #[error("Key not found")]
    KeyNotFound,
    #[error("Key already exists")]
    KeyAlreadyExists,
    #[error("Storage error: {0}")]
    StorageError(String),
}

pub trait KeyStorage {
    fn insert(&self, api_key: &ApiKey) -> Result<ApiKey, ApiKeyError>;
    fn retrieve(&self, api_key: &ApiKey) -> Result<ApiKey, ApiKeyError>;
    fn delete(&self, api_key: &ApiKey) -> Result<bool, ApiKeyError>;
    fn find_by_key(&self, value: &str) -> Result<ApiKey, ApiKeyError>;
}

impl KeyStorage for InMemoryApiKeyStorage {
    fn insert(&self, api_key: &ApiKey) -> Result<ApiKey, ApiKeyError> {
        let storage_key = api_key.storage_key();
        match self.map.get(&storage_key) {
            Some(_) => Err(ApiKeyStorageError::KeyAlreadyExists.into()),
            None => {
                self.map.insert(storage_key, api_key.clone());
                Ok(api_key.clone())
            }
        }
    }

    fn retrieve(&self, api_key: &ApiKey) -> Result<ApiKey, ApiKeyError> {
        self.map
            .get(&api_key.storage_key())
            .map(|r| r.clone())
            .ok_or(ApiKeyStorageError::KeyNotFound.into())
    }

    fn delete(&self, api_key: &ApiKey) -> Result<bool, ApiKeyError> {
        let storage_key = api_key.storage_key();
        if !self.map.contains_key(&storage_key) {
            return Err(ApiKeyStorageError::KeyNotFound.into());
        }
        self.map.remove(&storage_key);
        Ok(true)
    }

    fn find_by_key(&self, value: &str) -> Result<ApiKey, ApiKeyError> {
        self.map
            .iter()
            .find(|r| r.value().key().as_ref() == value)
            .map(|r| r.value().clone())
            .ok_or(ApiKeyStorageError::KeyNotFound.into())
    }
}