mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-11 10:05:41 +00:00
pow stats for solution and verification
This commit is contained in:
4
migrations/20210509135118_mcaptcha_pow_solved_stats.sql
Normal file
4
migrations/20210509135118_mcaptcha_pow_solved_stats.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS mcaptcha_pow_solved_stats (
|
||||||
|
config_id INTEGER references mcaptcha_config(config_id) ON DELETE CASCADE,
|
||||||
|
solved_at timestamptz NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS mcaptcha_pow_confirmed_stats (
|
||||||
|
config_id INTEGER references mcaptcha_config(config_id) ON DELETE CASCADE,
|
||||||
|
confirm_ed timestamptz NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
@@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
pub async fn fetched(key: &str, db: &PgPool) {
|
/// record PoWConfig fetches
|
||||||
|
#[inline]
|
||||||
|
pub async fn record_fetch(key: &str, db: &PgPool) {
|
||||||
let _ = sqlx::query!(
|
let _ = sqlx::query!(
|
||||||
"INSERT INTO mcaptcha_pow_fetched_stats
|
"INSERT INTO mcaptcha_pow_fetched_stats
|
||||||
(config_id) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1))",
|
(config_id) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1))",
|
||||||
@@ -26,3 +28,27 @@ pub async fn fetched(key: &str, db: &PgPool) {
|
|||||||
.execute(db)
|
.execute(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// record PoWConfig solves
|
||||||
|
#[inline]
|
||||||
|
pub async fn record_solve(key: &str, db: &PgPool) {
|
||||||
|
let _ = sqlx::query!(
|
||||||
|
"INSERT INTO mcaptcha_pow_solved_stats
|
||||||
|
(config_id) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1))",
|
||||||
|
&key,
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// record PoWConfig confirms
|
||||||
|
#[inline]
|
||||||
|
pub async fn record_confirm(key: &str, db: &PgPool) {
|
||||||
|
let _ = sqlx::query!(
|
||||||
|
"INSERT INTO mcaptcha_pow_confirmed_stats
|
||||||
|
(config_id) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1))",
|
||||||
|
&key,
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ use actix_web::{web, HttpResponse, Responder};
|
|||||||
use m_captcha::{defense::LevelBuilder, master::AddSiteBuilder, DefenseBuilder, MCaptchaBuilder};
|
use m_captcha::{defense::LevelBuilder, master::AddSiteBuilder, DefenseBuilder, MCaptchaBuilder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::record_fetch;
|
||||||
use super::GetDurationResp;
|
use super::GetDurationResp;
|
||||||
use super::I32Levels;
|
use super::I32Levels;
|
||||||
use crate::api::v1::mcaptcha::stats::fetched;
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ pub struct GetConfigPayload {
|
|||||||
|
|
||||||
// API keys are mcaptcha actor names
|
// API keys are mcaptcha actor names
|
||||||
|
|
||||||
|
/// get PoW configuration for an mcaptcha key
|
||||||
pub async fn get_config(
|
pub async fn get_config(
|
||||||
payload: web::Json<GetConfigPayload>,
|
payload: web::Json<GetConfigPayload>,
|
||||||
data: web::Data<Data>,
|
data: web::Data<Data>,
|
||||||
@@ -68,7 +69,7 @@ pub async fn get_config(
|
|||||||
.expect("mcaptcha should be initialized and ready to go");
|
.expect("mcaptcha should be initialized and ready to go");
|
||||||
// background it. would require data::Data to be static
|
// background it. would require data::Data to be static
|
||||||
// to satidfy lifetime
|
// to satidfy lifetime
|
||||||
fetched(&payload.key, &data.db).await;
|
record_fetch(&payload.key, &data.db).await;
|
||||||
Ok(HttpResponse::Ok().json(config))
|
Ok(HttpResponse::Ok().json(config))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +79,10 @@ pub async fn get_config(
|
|||||||
None => Err(ServiceError::TokenNotFound),
|
None => Err(ServiceError::TokenNotFound),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Call this when [MCaptcha][m_captcha::MCaptcha] is not in master.
|
||||||
|
///
|
||||||
|
/// This fn gets mcaptcha config from database, builds [Defense][m_captcha::Defense],
|
||||||
|
/// creates [MCaptcha][m_captcha::MCaptcha] and adds it to [Master][m_captcha::Defense]
|
||||||
async fn init_mcaptcha(data: &Data, key: &str) -> ServiceResult<()> {
|
async fn init_mcaptcha(data: &Data, key: &str) -> ServiceResult<()> {
|
||||||
// get levels
|
// get levels
|
||||||
let levels_fut = sqlx::query_as!(
|
let levels_fut = sqlx::query_as!(
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pub mod verify_token;
|
|||||||
|
|
||||||
pub use super::mcaptcha::duration::GetDurationResp;
|
pub use super::mcaptcha::duration::GetDurationResp;
|
||||||
pub use super::mcaptcha::levels::I32Levels;
|
pub use super::mcaptcha::levels::I32Levels;
|
||||||
|
use crate::api::v1::mcaptcha::stats::*;
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
use crate::define_resource;
|
use crate::define_resource;
|
||||||
|
|||||||
@@ -14,26 +14,34 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
//! PoW Verification module
|
||||||
|
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
use m_captcha::pow::Work;
|
use m_captcha::pow::Work;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::record_solve;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
/// validation token that clients receive as proof for submiting
|
||||||
|
/// valid PoW
|
||||||
pub struct ValidationToken {
|
pub struct ValidationToken {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// API keys are mcaptcha actor names
|
// API keys are mcaptcha actor names
|
||||||
|
|
||||||
|
/// route handler that verifies PoW and issues a solution token
|
||||||
|
/// if verification is successful
|
||||||
pub async fn verify_pow(
|
pub async fn verify_pow(
|
||||||
payload: web::Json<Work>,
|
payload: web::Json<Work>,
|
||||||
data: web::Data<Data>,
|
data: web::Data<Data>,
|
||||||
) -> ServiceResult<impl Responder> {
|
) -> ServiceResult<impl Responder> {
|
||||||
|
let key = payload.key.clone();
|
||||||
let res = data.captcha.verify_pow(payload.into_inner()).await?;
|
let res = data.captcha.verify_pow(payload.into_inner()).await?;
|
||||||
|
record_solve(&key, &data.db).await;
|
||||||
let payload = ValidationToken { token: res };
|
let payload = ValidationToken { token: res };
|
||||||
Ok(HttpResponse::Ok().json(payload))
|
Ok(HttpResponse::Ok().json(payload))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,13 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
//! PoW success token module
|
||||||
|
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
use m_captcha::cache::messages::VerifyCaptchaResult;
|
use m_captcha::cache::messages::VerifyCaptchaResult;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::record_confirm;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
@@ -29,16 +31,19 @@ pub struct CaptchaValidateResp {
|
|||||||
|
|
||||||
// API keys are mcaptcha actor names
|
// API keys are mcaptcha actor names
|
||||||
|
|
||||||
|
/// route hander that validates a PoW solution token
|
||||||
pub async fn validate_captcha_token(
|
pub async fn validate_captcha_token(
|
||||||
payload: web::Json<VerifyCaptchaResult>,
|
payload: web::Json<VerifyCaptchaResult>,
|
||||||
data: web::Data<Data>,
|
data: web::Data<Data>,
|
||||||
) -> ServiceResult<impl Responder> {
|
) -> ServiceResult<impl Responder> {
|
||||||
|
let key = payload.key.clone();
|
||||||
let res = data
|
let res = data
|
||||||
.captcha
|
.captcha
|
||||||
.validate_verification_tokens(payload.into_inner())
|
.validate_verification_tokens(payload.into_inner())
|
||||||
.await?;
|
.await?;
|
||||||
let payload = CaptchaValidateResp { valid: res };
|
let payload = CaptchaValidateResp { valid: res };
|
||||||
println!("{:?}", &payload);
|
record_confirm(&key, &data.db).await;
|
||||||
|
//println!("{:?}", &payload);
|
||||||
Ok(HttpResponse::Ok().json(payload))
|
Ok(HttpResponse::Ok().json(payload))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user