Added claudflare Turnstile captcha support
This commit is contained in:
@@ -76,6 +76,7 @@ struct LandingTemplate<'a> {
|
||||
testimonials: Vec<Testimonial>,
|
||||
site_domain: String,
|
||||
review_count: usize,
|
||||
turnstile_site_key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
@@ -138,6 +139,12 @@ async fn landing_page(request: Request, db: Database) -> cot::Result<Response> {
|
||||
.await?
|
||||
.map(|s| s.value)
|
||||
.unwrap_or_default();
|
||||
let turnstile_key = "turnstile_site_key".to_string();
|
||||
let turnstile_site_key = query!(Setting, $key == turnstile_key)
|
||||
.get(&db)
|
||||
.await?
|
||||
.map(|s| s.value)
|
||||
.unwrap_or_default();
|
||||
let mut testimonials = Testimonial::objects().all(&db).await?;
|
||||
testimonials.retain(|t| t.status == "active");
|
||||
testimonials.sort_by(|a, b| a.sort_order.cmp(&b.sort_order));
|
||||
@@ -151,6 +158,7 @@ async fn landing_page(request: Request, db: Database) -> cot::Result<Response> {
|
||||
testimonials,
|
||||
site_domain,
|
||||
review_count,
|
||||
turnstile_site_key,
|
||||
}
|
||||
.render()?;
|
||||
html_response(body, lang)
|
||||
@@ -161,6 +169,8 @@ struct LeadForm {
|
||||
name: String,
|
||||
phone: Option<String>,
|
||||
comment: Option<String>,
|
||||
#[serde(default, rename = "cf-turnstile-response")]
|
||||
cf_turnstile_response: Option<String>,
|
||||
}
|
||||
|
||||
async fn submit_lead(request: Request, db: Database) -> cot::Result<Response> {
|
||||
@@ -170,6 +180,37 @@ async fn submit_lead(request: Request, db: Database) -> cot::Result<Response> {
|
||||
let form: LeadForm =
|
||||
serde_html_form::from_bytes(&bytes).map_err(|e| cot::Error::internal(e.to_string()))?;
|
||||
|
||||
// Turnstile CAPTCHA verification (only when secret key is configured)
|
||||
let secret_key_name = "turnstile_secret_key".to_string();
|
||||
let secret_key = query!(Setting, $key == secret_key_name)
|
||||
.get(&db)
|
||||
.await?
|
||||
.map(|s| s.value)
|
||||
.filter(|s| !s.is_empty());
|
||||
if let Some(secret) = secret_key {
|
||||
let token = form.cf_turnstile_response.as_deref().unwrap_or("");
|
||||
let client = reqwest::Client::new();
|
||||
let resp = client
|
||||
.post("https://challenges.cloudflare.com/turnstile/v0/siteverify")
|
||||
.json(&serde_json::json!({
|
||||
"secret": secret,
|
||||
"response": token
|
||||
}))
|
||||
.send()
|
||||
.await;
|
||||
let verified = match resp {
|
||||
Ok(r) => r
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.map(|v| v["success"].as_bool() == Some(true))
|
||||
.unwrap_or(false),
|
||||
Err(_) => false,
|
||||
};
|
||||
if !verified {
|
||||
return Redirect::new(format!("/?lang={}", lang.code())).into_response();
|
||||
}
|
||||
}
|
||||
|
||||
let mut lead = Lead {
|
||||
id: Auto::auto(),
|
||||
name: form.name,
|
||||
|
||||
Reference in New Issue
Block a user