ncryptf/rocket/
mod.rs

1use rocket::Request;
2
3/// The Ncryptf JSON content type
4pub const NCRYPTF_CONTENT_TYPE: &str = "application/vnd.ncryptf+json";
5
6/// The amount of time (in either direction) a request time may differ by and still be accepted.
7pub const NCRYPTF_DRIFT_ALLOWANCE: i32 = 90;
8
9/// The cached public key from the request
10pub struct RequestPublicKey(pub Vec<u8>);
11
12/// The cached signing public key from the request
13pub struct RequestSigningPublicKey(pub Vec<u8>);
14
15mod json;
16pub use json::{respond_to_with_ncryptf, Error as JsonError, Json, JsonResponse, parse_body};
17mod ek;
18pub use ek::{EncryptionKey, ExportableEncryptionKeyData};
19mod auth;
20pub use auth::{AuthorizationTrait, TokenError, RequestData, *};
21
22use cached::{Cached, IOCached};
23use std::sync::{Arc, Mutex};
24
25/// A wrapper for supported cache types
26pub enum CacheWrapper {
27    TimedCache(Arc<Mutex<cached::TimedCache<String, EncryptionKey>>>),
28    UnboundCache(Arc<Mutex<cached::UnboundCache<String, EncryptionKey>>>),
29    RedisCache(Arc<Mutex<cached::RedisCache<String, EncryptionKey>>>),
30}
31
32impl CacheWrapper {
33    pub fn get(&self, key: &str) -> Option<EncryptionKey> {
34        match self {
35            CacheWrapper::TimedCache(cache) => {
36                let mut guard = cache.lock().ok()?;
37                guard.cache_get(&key.to_string()).cloned()
38            }
39            CacheWrapper::UnboundCache(cache) => {
40                let mut guard = cache.lock().ok()?;
41                guard.cache_get(&key.to_string()).cloned()
42            }
43            CacheWrapper::RedisCache(cache) => {
44                let guard = cache.lock().ok()?;
45                match guard.cache_get(&key.to_string()) {
46                    Ok(value) => value,
47                    Err(_) => None,
48                }
49            }
50        }
51    }
52    
53    pub fn set(&self, key: String, value: EncryptionKey) {
54        match self {
55            CacheWrapper::TimedCache(cache) => {
56                if let Ok(mut guard) = cache.lock() {
57                    guard.cache_set(key, value);
58                }
59            }
60            CacheWrapper::UnboundCache(cache) => {
61                if let Ok(mut guard) = cache.lock() {
62                    guard.cache_set(key, value);
63                }
64            }
65            CacheWrapper::RedisCache(cache) => {
66                if let Ok(guard) = cache.lock() {
67                    let _ = guard.cache_set(key, value);
68                }
69            }
70        }
71    }
72    
73    pub fn remove(&self, key: &str) -> Option<EncryptionKey> {
74        match self {
75            CacheWrapper::TimedCache(cache) => {
76                let mut guard = cache.lock().ok()?;
77                guard.cache_remove(&key.to_string())
78            }
79            CacheWrapper::UnboundCache(cache) => {
80                let mut guard = cache.lock().ok()?;
81                guard.cache_remove(&key.to_string())
82            }
83            CacheWrapper::RedisCache(cache) => {
84                let guard = cache.lock().ok()?;
85                match guard.cache_remove(&key.to_string()) {
86                    Ok(value) => value,
87                    Err(_) => None,
88                }
89            }
90        }
91    }
92}
93
94/// Get the managed cache from Rocket state
95/// Returns a cache wrapper that can handle different cache types
96#[doc(hidden)]
97pub fn get_cache(req: &Request<'_>) -> Result<CacheWrapper, anyhow::Error> {
98    // Try cached::TimedCache
99    if let Some(cache) = req.rocket().state::<Arc<Mutex<cached::TimedCache<String, EncryptionKey>>>>() {
100        return Ok(CacheWrapper::TimedCache(cache.clone()));
101    }
102    
103    // Try cached::UnboundCache
104    if let Some(cache) = req.rocket().state::<Arc<Mutex<cached::UnboundCache<String, EncryptionKey>>>>() {
105        return Ok(CacheWrapper::UnboundCache(cache.clone()));
106    }
107
108    // Try cached::RedisCache
109    if let Some(cache) = req.rocket().state::<Arc<Mutex<cached::RedisCache<String, EncryptionKey>>>>() {
110        return Ok(CacheWrapper::RedisCache(cache.clone()));
111    }
112
113    Err(anyhow::anyhow!(
114        "No supported cache found in rocket state. Make sure to add your cache as managed state with .manage(Arc::new(Mutex::new(your_cache)))"
115    ))
116}