use super::*;
#[derive(Deserialize, Debug)]
pub struct Request {
pub secret: String,
pub hostname: Option<String>,
pub token: String,
pub ip: Option<String>,
}
#[derive(Serialize, Debug)]
pub struct Response {
score: f32,
action: String,
timestamp: time::PrimitiveDateTime,
}
#[derive(Serialize, Debug)]
struct RemoteRequest {
secret: String,
response: String,
remoteip: Option<String>,
}
#[derive(Deserialize, Serialize, Debug)]
struct RemoteResponse {
success: bool,
score: Option<f32>,
action: Option<String>,
#[serde(rename(deserialize = "challenge_ts"))]
timestamp: Option<String>,
hostname: Option<String>,
#[serde(rename(deserialize = "error-codes"))]
errors: Option<Vec<String>>,
}
#[post("")]
pub async fn route(req: web::Json<Request>) -> Result<impl Responder, impl ResponseError> {
let req = req.into_inner();
let time_format =
time::format_description::parse("[year]-[month]-[day]T[hour]:[minute]:[second]Z")
.unwrap();
if let Ok(value) = std::env::var("ALWAYS_TRUE") {
if value == "true" {
return Ok(web::Json(Response {
score: 1.0,
action: "always_true".to_string(),
timestamp: time::PrimitiveDateTime::parse(&time::OffsetDateTime::now_utc().format(&time_format).unwrap(), &time_format).unwrap(),
}));
}
}
let remote = reqwest::Client::new()
.post("https://www.google.com/recaptcha/api/siteverify")
.form(&RemoteRequest {
secret: req.secret,
response: req.token,
remoteip: req.ip,
})
.send()
.await
.unwrap()
.json::<RemoteResponse>()
.await
.unwrap();
match remote.success {
false => {
let errors = remote.errors;
if errors.is_some()
&& errors.as_ref().unwrap().len() == 1
&& (errors.as_ref().unwrap().first().unwrap() == "invalid-input-response"
|| errors.unwrap().first().unwrap() == "timeout-or-duplicate")
{
return Err(ErrorCode::Unauthorised);
}
Err(ErrorCode::BadRequest)
}
true => {
Ok(web::Json(Response {
score: remote.score.unwrap(),
action: remote.action.unwrap(),
timestamp: time::PrimitiveDateTime::parse(&remote.timestamp.unwrap(), &time_format)
.unwrap(),
}))
}
}
}