1#![warn(missing_docs)]
7use serde::{Deserialize, Serialize};
23
24pub use libmcaptcha::defense::Level;
25
26pub mod errors;
27pub mod ops;
28#[cfg(feature = "test")]
29pub mod tests;
30
31use dev::*;
32pub use ops::GetConnection;
33
34pub mod prelude {
35 pub use super::errors::*;
38 pub use super::ops::*;
39 pub use super::*;
40}
41
42pub mod dev {
43 pub use super::prelude::*;
45 pub use async_trait::async_trait;
46}
47
48#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
49pub struct Register<'a> {
51 pub username: &'a str,
53 pub secret: &'a str,
55 pub hash: &'a str,
57 pub email: Option<&'a str>,
59}
60
61#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
62pub struct UpdateEmail<'a> {
64 pub username: &'a str,
66 pub new_email: &'a str,
68}
69
70#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
71pub enum Login<'a> {
73 Username(&'a str),
75 Email(&'a str),
77}
78
79#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
80pub struct NameHash {
82 pub username: String,
84 pub hash: String,
86}
87
88#[async_trait]
89pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
92 async fn ping(&self) -> bool;
94
95 async fn register(&self, p: &Register) -> DBResult<()>;
97
98 async fn delete_user(&self, username: &str) -> DBResult<()>;
100
101 async fn username_exists(&self, username: &str) -> DBResult<bool>;
103
104 async fn get_email(&self, username: &str) -> DBResult<Option<String>>;
106
107 async fn email_exists(&self, email: &str) -> DBResult<bool>;
109
110 async fn update_email(&self, p: &UpdateEmail) -> DBResult<()>;
112
113 async fn get_password(&self, l: &Login) -> DBResult<NameHash>;
115
116 async fn update_password(&self, p: &NameHash) -> DBResult<()>;
118
119 async fn update_username(&self, current: &str, new: &str) -> DBResult<()>;
121
122 async fn get_secret(&self, username: &str) -> DBResult<Secret>;
124
125 async fn get_secret_from_captcha(&self, key: &str) -> DBResult<Secret>;
127
128 async fn update_secret(&self, username: &str, secret: &str) -> DBResult<()>;
130
131 async fn create_captcha(&self, username: &str, p: &CreateCaptcha) -> DBResult<()>;
133
134 async fn get_captcha_config(&self, username: &str, key: &str) -> DBResult<Captcha>;
136
137 async fn get_all_user_captchas(&self, username: &str) -> DBResult<Vec<Captcha>>;
139
140 async fn update_captcha_metadata(
142 &self,
143 username: &str,
144 p: &CreateCaptcha,
145 ) -> DBResult<()>;
146
147 async fn update_captcha_key(
149 &self,
150 username: &str,
151 old_key: &str,
152 new_key: &str,
153 ) -> DBResult<()>;
154
155 async fn add_captcha_levels(
157 &self,
158 username: &str,
159 captcha_key: &str,
160 levels: &[Level],
161 ) -> DBResult<()>;
162
163 async fn captcha_exists(
165 &self,
166 username: Option<&str>,
167 captcha_key: &str,
168 ) -> DBResult<bool>;
169
170 async fn delete_captcha_levels(
172 &self,
173 username: &str,
174 captcha_key: &str,
175 ) -> DBResult<()>;
176
177 async fn delete_captcha(&self, username: &str, captcha_key: &str) -> DBResult<()>;
179
180 async fn get_captcha_levels(
182 &self,
183 username: Option<&str>,
184 captcha_key: &str,
185 ) -> DBResult<Vec<Level>>;
186
187 async fn get_captcha_cooldown(&self, captcha_key: &str) -> DBResult<i32>;
189
190 async fn add_traffic_pattern(
192 &self,
193 username: &str,
194 captcha_key: &str,
195 pattern: &TrafficPattern,
196 ) -> DBResult<()>;
197
198 async fn get_traffic_pattern(
200 &self,
201 username: &str,
202 captcha_key: &str,
203 ) -> DBResult<TrafficPattern>;
204
205 async fn get_all_easy_captchas(
207 &self,
208 limit: usize,
209 offset: usize,
210 ) -> DBResult<Vec<EasyCaptcha>>;
211
212 async fn delete_traffic_pattern(
214 &self,
215 username: &str,
216 captcha_key: &str,
217 ) -> DBResult<()>;
218
219 async fn create_notification(&self, p: &AddNotification) -> DBResult<()>;
221
222 async fn get_all_unread_notifications(
224 &self,
225 username: &str,
226 ) -> DBResult<Vec<Notification>>;
227
228 async fn mark_notification_read(&self, username: &str, id: i32) -> DBResult<()>;
230
231 async fn record_fetch(&self, key: &str) -> DBResult<()>;
233
234 async fn record_solve(&self, key: &str) -> DBResult<()>;
236
237 async fn record_confirm(&self, key: &str) -> DBResult<()>;
239
240 async fn fetch_config_fetched(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
242
243 async fn fetch_solve(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
245
246 async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
248
249 async fn analysis_save(
251 &self,
252 captcha_id: &str,
253 d: &CreatePerformanceAnalytics,
254 ) -> DBResult<()>;
255
256 async fn analytics_fetch(
258 &self,
259 captcha_id: &str,
260 limit: usize,
261 offset: usize,
262 ) -> DBResult<Vec<PerformanceAnalytics>>;
263
264 async fn analytics_create_psuedo_id_if_not_exists(
266 &self,
267 captcha_id: &str,
268 ) -> DBResult<()>;
269
270 async fn analytics_get_psuedo_id_from_capmaign_id(
272 &self,
273 captcha_id: &str,
274 ) -> DBResult<String>;
275
276 async fn analytics_get_capmaign_id_from_psuedo_id(
278 &self,
279 psuedo_id: &str,
280 ) -> DBResult<String>;
281
282 async fn analytics_delete_all_records_for_campaign(
284 &self,
285 campaign_id: &str,
286 ) -> DBResult<()>;
287
288 async fn analytics_captcha_is_published(&self, campaign_id: &str) -> DBResult<bool> {
290 match self
291 .analytics_get_psuedo_id_from_capmaign_id(campaign_id)
292 .await
293 {
294 Ok(_) => Ok(true),
295 Err(errors::DBError::CaptchaNotFound) => Ok(false),
296 Err(e) => Err(e),
297 }
298 }
299
300 async fn analytics_get_all_psuedo_ids(&self, page: usize) -> DBResult<Vec<String>>;
302
303 async fn update_max_nonce_for_level(
305 &self,
306 captcha_key: &str,
307 difficulty_factor: u32,
308 latest_nonce: u32,
309 ) -> DBResult<()>;
310
311 async fn get_max_nonce_for_level(
313 &self,
314 captcha_key: &str,
315 difficulty_factor: u32,
316 ) -> DBResult<u32>;
317
318 async fn stats_get_num_logs_under_time(&self, duration: u32) -> DBResult<usize>;
320
321 async fn stats_get_entry_at_location_for_time_limit_asc(
324 &self,
325 duration: u32,
326 location: u32,
327 ) -> DBResult<Option<usize>>;
328}
329
330#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
331pub struct CreatePerformanceAnalytics {
333 pub time: u32,
335 pub difficulty_factor: u32,
337 pub worker_type: String,
339}
340
341#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
342pub struct PerformanceAnalytics {
344 pub id: usize,
346 pub time: u32,
348 pub difficulty_factor: u32,
350 pub worker_type: String,
352}
353
354#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
355pub struct StatsUnixTimestamp {
357 pub config_fetches: Vec<i64>,
359 pub solves: Vec<i64>,
361 pub confirms: Vec<i64>,
363}
364
365#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
366pub struct Notification {
368 pub name: Option<String>,
370 pub heading: Option<String>,
372 pub message: Option<String>,
374 pub received: Option<i64>,
376 pub id: Option<i32>,
378}
379
380#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
381pub struct AddNotification<'a> {
383 pub to: &'a str,
385 pub from: &'a str,
387 pub heading: &'a str,
389 pub message: &'a str,
391}
392
393#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)]
394pub struct EasyCaptcha {
396 pub traffic_pattern: TrafficPattern,
398 pub key: String,
400 pub description: String,
402 pub username: String,
404}
405
406#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)]
407pub struct TrafficPattern {
409 pub avg_traffic: u32,
411 pub peak_sustainable_traffic: u32,
413 pub broke_my_site_traffic: Option<u32>,
415}
416
417#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
418pub struct CreateCaptcha<'a> {
420 pub duration: i32,
422 pub description: &'a str,
424 pub key: &'a str,
426}
427
428#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
429pub struct Captcha {
431 pub config_id: i32,
433 pub duration: i32,
435 pub description: String,
437 pub key: String,
439}
440
441#[derive(Clone, Debug, Deserialize, PartialEq, Default, Serialize)]
442pub struct Secret {
444 pub secret: String,
446}
447pub trait CloneSPDatabase {
449 fn clone_db(&self) -> Box<dyn MCDatabase>;
451}
452
453impl<T> CloneSPDatabase for T
454where
455 T: MCDatabase + Clone + 'static,
456{
457 fn clone_db(&self) -> Box<dyn MCDatabase> {
458 Box::new(self.clone())
459 }
460}
461
462impl Clone for Box<dyn MCDatabase> {
463 fn clone(&self) -> Self {
464 (**self).clone_db()
465 }
466}