salvo_captcha/storage/
mod.rs1use std::{sync::Arc, time::Duration};
13
14#[cfg(feature = "cacache-storage")]
15mod cacache_storage;
16mod memory_storage;
17
18#[cfg_attr(docsrs, doc(cfg(feature = "cacache-storage")))]
19#[cfg(feature = "cacache-storage")]
20pub use cacache_storage::*;
21pub use memory_storage::*;
22
23pub trait CaptchaStorage: Send + Sync + 'static {
29 type Error: std::error::Error + Send;
31
32 fn store_answer(
34 &self,
35 answer: String,
36 ) -> impl std::future::Future<Output = Result<String, Self::Error>> + Send;
37
38 fn get_answer(
40 &self,
41 token: &str,
42 ) -> impl std::future::Future<Output = Result<Option<String>, Self::Error>> + Send;
43
44 fn clear_expired(
46 &self,
47 expired_after: Duration,
48 ) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send;
49
50 fn clear_by_token(
52 &self,
53 token: &str,
54 ) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send;
55
56 fn new_captcha<G: crate::CaptchaGenerator>(
60 &self,
61 generator: G,
62 ) -> impl std::future::Future<
63 Output = Result<(String, Vec<u8>), either::Either<Self::Error, G::Error>>,
64 > + Send {
65 async move {
66 let (answer, image) = generator.new_captcha().await.map_err(either::Right)?;
67 Ok((
68 self.store_answer(answer).await.map_err(either::Left)?,
69 image,
70 ))
71 }
72 }
73}
74
75impl<T> CaptchaStorage for Arc<T>
76where
77 T: CaptchaStorage,
78{
79 type Error = T::Error;
80
81 fn store_answer(
82 &self,
83 answer: String,
84 ) -> impl std::future::Future<Output = Result<String, Self::Error>> + Send {
85 self.as_ref().store_answer(answer)
86 }
87
88 fn get_answer(
89 &self,
90 token: &str,
91 ) -> impl std::future::Future<Output = Result<Option<String>, Self::Error>> + Send {
92 self.as_ref().get_answer(token)
93 }
94
95 fn clear_expired(
96 &self,
97 expired_after: Duration,
98 ) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send {
99 self.as_ref().clear_expired(expired_after)
100 }
101
102 fn clear_by_token(
103 &self,
104 token: &str,
105 ) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send {
106 self.as_ref().clear_by_token(token)
107 }
108}