mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2025-02-16 16:39:46 +03:00
feat: log pow performance stats while pow verification
This commit is contained in:
parent
679a35216c
commit
2cf5e48d8e
1 changed files with 115 additions and 2 deletions
|
@ -32,6 +32,27 @@ pub struct ValidationToken {
|
|||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct ApiWork {
|
||||
pub string: String,
|
||||
pub result: String,
|
||||
pub nonce: u64,
|
||||
pub key: String,
|
||||
pub time: Option<u32>,
|
||||
pub worker_type: Option<String>,
|
||||
}
|
||||
|
||||
impl From<ApiWork> for Work {
|
||||
fn from(value: ApiWork) -> Self {
|
||||
Self {
|
||||
string: value.string,
|
||||
nonce: value.nonce,
|
||||
result: value.result,
|
||||
key: value.key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// API keys are mcaptcha actor names
|
||||
|
||||
/// route handler that verifies PoW and issues a solution token
|
||||
|
@ -39,7 +60,7 @@ pub struct ValidationToken {
|
|||
#[my_codegen::post(path = "V1_API_ROUTES.pow.verify_pow()")]
|
||||
pub async fn verify_pow(
|
||||
req: HttpRequest,
|
||||
payload: web::Json<Work>,
|
||||
payload: web::Json<ApiWork>,
|
||||
data: AppData,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
#[cfg(not(test))]
|
||||
|
@ -52,8 +73,19 @@ pub async fn verify_pow(
|
|||
let ip = "127.0.1.1".into();
|
||||
|
||||
let key = payload.key.clone();
|
||||
let res = data.captcha.verify_pow(payload.into_inner(), ip).await?;
|
||||
let payload = payload.into_inner();
|
||||
let worker_type = payload.worker_type.clone();
|
||||
let time = payload.time;
|
||||
let (res, difficulty_factor) = data.captcha.verify_pow(payload.into(), ip).await?;
|
||||
data.stats.record_solve(&data, &key).await?;
|
||||
if time.is_some() && worker_type.is_some() {
|
||||
let analytics = db_core::CreatePerformanceAnalytics {
|
||||
difficulty_factor,
|
||||
time: time.unwrap(),
|
||||
worker_type: worker_type.unwrap(),
|
||||
};
|
||||
data.db.analysis_save(&key, &analytics).await?;
|
||||
}
|
||||
let payload = ValidationToken { token: res };
|
||||
Ok(HttpResponse::Ok().json(payload))
|
||||
}
|
||||
|
@ -81,6 +113,81 @@ pub mod tests {
|
|||
verify_pow_works(data).await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn verify_analytics_pow_works_pg() {
|
||||
let data = crate::tests::pg::get_data().await;
|
||||
verify_analytics_pow_works(data).await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn verify_analytics_pow_works_maria() {
|
||||
let data = crate::tests::maria::get_data().await;
|
||||
verify_analytics_pow_works(data).await;
|
||||
}
|
||||
|
||||
pub async fn verify_analytics_pow_works(data: ArcData) {
|
||||
const NAME: &str = "powanalyticsuser";
|
||||
const PASSWORD: &str = "testingpas";
|
||||
const EMAIL: &str = "powanalyticsuser@a.com";
|
||||
let data = &data;
|
||||
|
||||
delete_user(data, NAME).await;
|
||||
|
||||
register_and_signin(data, NAME, EMAIL, PASSWORD).await;
|
||||
let (_, _signin_resp, token_key) = add_levels_util(data, NAME, PASSWORD).await;
|
||||
let app = get_app!(data).await;
|
||||
|
||||
let get_config_payload = GetConfigPayload {
|
||||
key: token_key.key.clone(),
|
||||
};
|
||||
|
||||
// update and check changes
|
||||
|
||||
let get_config_resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&get_config_payload, V1_API_ROUTES.pow.get_config)
|
||||
.to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(get_config_resp.status(), StatusCode::OK);
|
||||
let config: PoWConfig = test::read_body_json(get_config_resp).await;
|
||||
|
||||
let pow = pow_sha256::ConfigBuilder::default()
|
||||
.salt(config.salt)
|
||||
.build()
|
||||
.unwrap();
|
||||
let work = pow
|
||||
.prove_work(&config.string.clone(), config.difficulty_factor)
|
||||
.unwrap();
|
||||
|
||||
let work = ApiWork {
|
||||
string: config.string.clone(),
|
||||
result: work.result,
|
||||
nonce: work.nonce,
|
||||
key: token_key.key.clone(),
|
||||
time: Some(100),
|
||||
worker_type: Some("wasm".into()),
|
||||
};
|
||||
|
||||
let pow_verify_resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&work, V1_API_ROUTES.pow.verify_pow).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(pow_verify_resp.status(), StatusCode::OK);
|
||||
let limit = 50;
|
||||
let offset = 0;
|
||||
let mut analytics = data
|
||||
.db
|
||||
.analytics_fetch(&token_key.key, limit, offset)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(analytics.len(), 1);
|
||||
let a = analytics.pop().unwrap();
|
||||
assert_eq!(a.time, work.time.unwrap());
|
||||
assert_eq!(a.worker_type, work.worker_type.unwrap());
|
||||
}
|
||||
|
||||
pub async fn verify_pow_works(data: ArcData) {
|
||||
const NAME: &str = "powverifyusr";
|
||||
const PASSWORD: &str = "testingpas";
|
||||
|
@ -129,6 +236,12 @@ pub mod tests {
|
|||
)
|
||||
.await;
|
||||
assert_eq!(pow_verify_resp.status(), StatusCode::OK);
|
||||
assert!(data
|
||||
.db
|
||||
.analytics_fetch(&token_key.key, 50, 0)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_empty());
|
||||
|
||||
let string_not_found = test::call_service(
|
||||
&app,
|
||||
|
|
Loading…
Add table
Reference in a new issue