apikeys_rs/storage/
mongodb_storage.rs

1use async_trait::async_trait;
2use bson::doc;
3use mongodb::{options::ClientOptions, Client, Database};
4
5use crate::{errors::ApiKeyStorageError, traits::ApiKeyStorage, types::ApiKey};
6
7#[derive(Clone)]
8pub struct MongoDBStorage {
9    db: Database,
10    collection_name: String,
11}
12
13impl MongoDBStorage {
14    pub async fn new(uri: &str, db_name: &str, collection_name: Option<String>) -> Result<Self, mongodb::error::Error> {
15        let client_options = ClientOptions::parse(uri).await?;
16        let client = Client::with_options(client_options)?;
17        let db = client.database(db_name);
18
19        Ok(Self {
20            db,
21            collection_name: match collection_name {
22                Some(name) => name,
23                None => "api_keys".to_string(),
24            },
25        })
26    }
27}
28
29#[async_trait]
30impl ApiKeyStorage for MongoDBStorage {
31    async fn store_api_key(&mut self, key: &str, value: &ApiKey) -> Result<String, ApiKeyStorageError> {
32        let collection = self.db.collection::<ApiKey>(self.collection_name.as_str());
33
34        let filter = doc! { "key": key };
35
36        match collection.find_one(filter, None).await {
37            Ok(result) => {
38                if result.is_some() {
39                    return Err(ApiKeyStorageError::KeyAlreadyExists);
40                }
41            }
42            Err(e) => return Err(ApiKeyStorageError::StorageError(e.to_string())),
43        }
44
45        match collection.insert_one(value, None).await {
46            Ok(result) => result,
47            Err(e) => return Err(ApiKeyStorageError::StorageError(e.to_string())),
48        };
49
50        Ok(key.to_string())
51    }
52
53    async fn retrieve_api_key(&self, key: &str) -> Result<ApiKey, ApiKeyStorageError> {
54        let collection = self.db.collection::<ApiKey>(self.collection_name.as_str());
55
56        let filter = doc! { "key": key };
57
58        let result = collection.find_one(filter, None).await;
59
60        let api_key = match result {
61            Ok(result) => match result {
62                Some(doc) => doc,
63                None => return Err(ApiKeyStorageError::KeyNotFound),
64            },
65            Err(e) => return Err(ApiKeyStorageError::StorageError(e.to_string())),
66        };
67
68        Ok(api_key)
69    }
70
71    async fn delete_api_key(&mut self, key: &str) -> Result<bool, ApiKeyStorageError> {
72        let collection = self.db.collection::<ApiKey>(self.collection_name.as_str());
73
74        let filter = doc! { "key": key };
75
76        let result = collection.delete_one(filter, None).await;
77
78        match result {
79            Ok(result) => Ok(result.deleted_count > 0),
80            Err(e) => return Err(ApiKeyStorageError::StorageError(e.to_string())),
81        }
82    }
83}