mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2025-03-14 13:08:27 +03:00
feat: add database method to get all easy captcha configurations with pagination
This commit is contained in:
parent
9bcf6af3ab
commit
91c235b3f4
6 changed files with 233 additions and 11 deletions
|
@ -202,6 +202,13 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
|
|||
captcha_key: &str,
|
||||
) -> DBResult<TrafficPattern>;
|
||||
|
||||
/// Get all easy captcha configurations on instance
|
||||
async fn get_all_easy_captchas(
|
||||
&self,
|
||||
limit: usize,
|
||||
offset: usize,
|
||||
) -> DBResult<Vec<EasyCaptcha>>;
|
||||
|
||||
/// 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 {
|
||||
|
|
|
@ -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!(
|
||||
|
|
58
db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json
generated
Normal file
58
db/db-sqlx-maria/.sqlx/query-c4aeba65b8bcd0f62ef79ed6549b4960d92dadfaf88401d7e2faacb93a2be169.json
generated
Normal file
|
@ -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"
|
||||
}
|
|
@ -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<Vec<EasyCaptcha>> {
|
||||
|
||||
struct InnerEasyCaptcha {
|
||||
captcha_key: String,
|
||||
peak_sustainable_traffic: i32,
|
||||
avg_traffic: i32,
|
||||
broke_my_site_traffic: Option<i32>,
|
||||
}
|
||||
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)]
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -669,13 +669,8 @@ impl MCDatabase for Database {
|
|||
username: &str,
|
||||
captcha_key: &str,
|
||||
) -> DBResult<TrafficPattern> {
|
||||
struct Traffic {
|
||||
peak_sustainable_traffic: i32,
|
||||
avg_traffic: i32,
|
||||
broke_my_site_traffic: Option<i32>,
|
||||
}
|
||||
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<Vec<EasyCaptcha>> {
|
||||
|
||||
struct InnerEasyCaptcha {
|
||||
key: String,
|
||||
peak_sustainable_traffic: i32,
|
||||
avg_traffic: i32,
|
||||
broke_my_site_traffic: Option<i32>,
|
||||
}
|
||||
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<InternaleCaptchaConfig> for Captcha {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InnerTraffic {
|
||||
peak_sustainable_traffic: i32,
|
||||
avg_traffic: i32,
|
||||
broke_my_site_traffic: Option<i32>,
|
||||
}
|
||||
|
||||
impl From<InnerTraffic> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue