apikeys_rs/storage/
mongodb_storage.rs1use 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}