From 91c235b3f40ff4bf2843fa7e285f06d31565a611 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Thu, 4 Jan 2024 23:28:50 +0530 Subject: [PATCH] feat: add database method to get all easy captcha configurations with pagination --- db/db-core/src/lib.rs | 16 ++++ db/db-core/src/tests.rs | 5 ++ ...b4960d92dadfaf88401d7e2faacb93a2be169.json | 58 ++++++++++++++ db/db-sqlx-maria/src/lib.rs | 48 ++++++++++++ ...525fcf804db932629ba38ccb64440494267f2.json | 41 ++++++++++ db/db-sqlx-postgres/src/lib.rs | 76 ++++++++++++++++--- 6 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json create mode 100644 db/db-sqlx-postgres/.sqlx/query-258b3eab56916d2fa89b86ea39a525fcf804db932629ba38ccb64440494267f2.json diff --git a/db/db-core/src/lib.rs b/db/db-core/src/lib.rs index 98b8336a..fe21e913 100644 --- a/db/db-core/src/lib.rs +++ b/db/db-core/src/lib.rs @@ -202,6 +202,13 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase { captcha_key: &str, ) -> DBResult; + /// Get all easy captcha configurations on instance + async fn get_all_easy_captchas( + &self, + limit: usize, + offset: usize, + ) -> DBResult>; + /// Delete traffic configuration async fn delete_traffic_pattern( &self, @@ -383,6 +390,15 @@ pub struct AddNotification<'a> { pub message: &'a str, } +#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)] +/// Represents Easy captcha configuration +pub struct EasyCaptcha { + /// traffic pattern of easy captcha + pub traffic_pattern: TrafficPattern, + /// captcha key/sitekey + pub key: String, +} + #[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)] /// User's traffic pattern; used in generating a captcha configuration pub struct TrafficPattern { diff --git a/db/db-core/src/tests.rs b/db/db-core/src/tests.rs index d0204a1a..ee91d828 100644 --- a/db/db-core/src/tests.rs +++ b/db/db-core/src/tests.rs @@ -223,6 +223,11 @@ pub async fn database_works<'a, T: MCDatabase>( tp ); + // get all traffic patterns + let patterns = db.get_all_easy_captchas(10, 0).await.unwrap(); + assert_eq!(patterns.get(0).as_ref().unwrap().key, c.key); + assert_eq!(&patterns.get(0).unwrap().traffic_pattern, tp); + // delete traffic pattern db.delete_traffic_pattern(p.username, c.key).await.unwrap(); assert!( diff --git a/db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json b/db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json new file mode 100644 index 00000000..a3ab00eb --- /dev/null +++ b/db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json @@ -0,0 +1,58 @@ +{ + "db_name": "MySQL", + "query": "SELECT \n mcaptcha_sitekey_user_provided_avg_traffic.avg_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.peak_sustainable_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.broke_my_site_traffic,\n mcaptcha_config.captcha_key\n FROM \n mcaptcha_sitekey_user_provided_avg_traffic \n INNER JOIN\n mcaptcha_config\n ON\n mcaptcha_config.config_id = mcaptcha_sitekey_user_provided_avg_traffic.config_id\n ORDER BY mcaptcha_config.config_id\n LIMIT ? OFFSET ?", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "avg_traffic", + "type_info": { + "type": "Long", + "flags": "NOT_NULL | NO_DEFAULT_VALUE", + "char_set": 63, + "max_size": 11 + } + }, + { + "ordinal": 1, + "name": "peak_sustainable_traffic", + "type_info": { + "type": "Long", + "flags": "NOT_NULL | NO_DEFAULT_VALUE", + "char_set": 63, + "max_size": 11 + } + }, + { + "ordinal": 2, + "name": "broke_my_site_traffic", + "type_info": { + "type": "Long", + "flags": "", + "char_set": 63, + "max_size": 11 + } + }, + { + "ordinal": 3, + "name": "captcha_key", + "type_info": { + "type": "VarString", + "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 400 + } + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + true, + false + ] + }, + "hash": "c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169" +} diff --git a/db/db-sqlx-maria/src/lib.rs b/db/db-sqlx-maria/src/lib.rs index 40e7f463..74ba0b3c 100644 --- a/db/db-sqlx-maria/src/lib.rs +++ b/db/db-sqlx-maria/src/lib.rs @@ -1273,6 +1273,54 @@ impl MCDatabase for Database { Err(e) => Err(map_row_not_found_err(e, DBError::CaptchaNotFound)), } } + + + /// Get all easy captcha configurations on instance + async fn get_all_easy_captchas( + &self, + limit: usize, + offset: usize, + ) -> DBResult> { + + struct InnerEasyCaptcha { + captcha_key: String, + peak_sustainable_traffic: i32, + avg_traffic: i32, + broke_my_site_traffic: Option, + } + let mut inner_res = sqlx::query_as!( + InnerEasyCaptcha, + "SELECT + mcaptcha_sitekey_user_provided_avg_traffic.avg_traffic, + mcaptcha_sitekey_user_provided_avg_traffic.peak_sustainable_traffic, + mcaptcha_sitekey_user_provided_avg_traffic.broke_my_site_traffic, + mcaptcha_config.captcha_key + FROM + mcaptcha_sitekey_user_provided_avg_traffic + INNER JOIN + mcaptcha_config + ON + mcaptcha_config.config_id = mcaptcha_sitekey_user_provided_avg_traffic.config_id + ORDER BY mcaptcha_config.config_id + LIMIT ? OFFSET ?", + limit as i64, + offset as i64 + ) + .fetch_all(&self.pool) + .await + .map_err(|e| map_row_not_found_err(e, DBError::TrafficPatternNotFound))?; + let mut res = Vec::with_capacity(inner_res.len()); + inner_res.drain(0..).for_each(|v| + res.push(EasyCaptcha { + key: v.captcha_key, + traffic_pattern: TrafficPattern { + broke_my_site_traffic: v.broke_my_site_traffic.as_ref().map(|v| *v as u32), + avg_traffic: v.avg_traffic as u32, + peak_sustainable_traffic: v.peak_sustainable_traffic as u32, + } + })); + Ok(res) + } } #[derive(Clone)] diff --git a/db/db-sqlx-postgres/.sqlx/query-258b3eab56916d2fa89b86ea39a525fcf804db932629ba38ccb64440494267f2.json b/db/db-sqlx-postgres/.sqlx/query-258b3eab56916d2fa89b86ea39a525fcf804db932629ba38ccb64440494267f2.json new file mode 100644 index 00000000..d0639efc --- /dev/null +++ b/db/db-sqlx-postgres/.sqlx/query-258b3eab56916d2fa89b86ea39a525fcf804db932629ba38ccb64440494267f2.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT \n mcaptcha_sitekey_user_provided_avg_traffic.avg_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.peak_sustainable_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.broke_my_site_traffic,\n mcaptcha_config.key\n FROM \n mcaptcha_sitekey_user_provided_avg_traffic \n INNER JOIN\n mcaptcha_config\n ON\n mcaptcha_config.config_id = mcaptcha_sitekey_user_provided_avg_traffic.config_id\n ORDER BY mcaptcha_config.config_id\n OFFSET $1 LIMIT $2; ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "avg_traffic", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "peak_sustainable_traffic", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "broke_my_site_traffic", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "key", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + true, + false + ] + }, + "hash": "258b3eab56916d2fa89b86ea39a525fcf804db932629ba38ccb64440494267f2" +} diff --git a/db/db-sqlx-postgres/src/lib.rs b/db/db-sqlx-postgres/src/lib.rs index 835d33e3..19bed122 100644 --- a/db/db-sqlx-postgres/src/lib.rs +++ b/db/db-sqlx-postgres/src/lib.rs @@ -669,13 +669,8 @@ impl MCDatabase for Database { username: &str, captcha_key: &str, ) -> DBResult { - struct Traffic { - peak_sustainable_traffic: i32, - avg_traffic: i32, - broke_my_site_traffic: Option, - } let res = sqlx::query_as!( - Traffic, + InnerTraffic, "SELECT avg_traffic, peak_sustainable_traffic, @@ -706,11 +701,54 @@ impl MCDatabase for Database { .fetch_one(&self.pool) .await .map_err(|e| map_row_not_found_err(e, DBError::TrafficPatternNotFound))?; - Ok(TrafficPattern { - broke_my_site_traffic: res.broke_my_site_traffic.as_ref().map(|v| *v as u32), - avg_traffic: res.avg_traffic as u32, - peak_sustainable_traffic: res.peak_sustainable_traffic as u32, - }) + Ok(res.into()) + } + + /// Get all easy captcha configurations on instance + async fn get_all_easy_captchas( + &self, + limit: usize, + offset: usize, + ) -> DBResult> { + + struct InnerEasyCaptcha { + key: String, + peak_sustainable_traffic: i32, + avg_traffic: i32, + broke_my_site_traffic: Option, + } + let mut inner_res = sqlx::query_as!( + InnerEasyCaptcha, + "SELECT + mcaptcha_sitekey_user_provided_avg_traffic.avg_traffic, + mcaptcha_sitekey_user_provided_avg_traffic.peak_sustainable_traffic, + mcaptcha_sitekey_user_provided_avg_traffic.broke_my_site_traffic, + mcaptcha_config.key + FROM + mcaptcha_sitekey_user_provided_avg_traffic + INNER JOIN + mcaptcha_config + ON + mcaptcha_config.config_id = mcaptcha_sitekey_user_provided_avg_traffic.config_id + ORDER BY mcaptcha_config.config_id + OFFSET $1 LIMIT $2; ", + offset as i32, + limit as i32 + ) + .fetch_all(&self.pool) + .await + .map_err(|e| map_row_not_found_err(e, DBError::TrafficPatternNotFound))?; + let mut res = Vec::with_capacity(inner_res.len()); + inner_res.drain(0..).for_each(|v| + res.push(EasyCaptcha { + key: v.key, + traffic_pattern: TrafficPattern { + broke_my_site_traffic: v.broke_my_site_traffic.as_ref().map(|v| *v as u32), + avg_traffic: v.avg_traffic as u32, + peak_sustainable_traffic: v.peak_sustainable_traffic as u32, + } + })); + Ok(res) } /// Delete traffic configuration @@ -1345,3 +1383,19 @@ impl From for Captcha { } } } + +struct InnerTraffic { + peak_sustainable_traffic: i32, + avg_traffic: i32, + broke_my_site_traffic: Option, +} + +impl From for TrafficPattern { + fn from(v: InnerTraffic) -> Self { + TrafficPattern { + broke_my_site_traffic: v.broke_my_site_traffic.as_ref().map(|v| *v as u32), + avg_traffic: v.avg_traffic as u32, + peak_sustainable_traffic: v.peak_sustainable_traffic as u32, + } + } +}