feat(corp/rih): implement backend captcha validation

Change-Id: Ia80a6aeb8c20bdacbf93356be31592ca4ba7fcdc
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8741
Autosubmit: tazjin <tazjin@tvl.su>
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2023-06-09 20:18:05 +03:00 committed by clbot
parent b3ca1a78eb
commit ba36a15b31
4 changed files with 43 additions and 1 deletions

View file

@ -94,7 +94,7 @@ resource "yandex_serverless_container" "rih_backend" {
service_account_id = yandex_iam_service_account.rih_backend.id
image {
url = "cr.yandex/crpkcq65tn6bhq6puq2o/rih-backend:dhgw6c4afancx1a3gac6day0bdgd9qhf"
url = "cr.yandex/crpkcq65tn6bhq6puq2o/rih-backend:q8kfd6kwc7p4wphzw1pj916y9m6icl9q"
}
secrets {

View file

@ -671,6 +671,7 @@ name = "rih-backend"
version = "0.1.0"
dependencies = [
"anyhow",
"attohttpc",
"log",
"rouille",
"rust-s3",

View file

@ -10,6 +10,11 @@ serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0"
uuid = { version = "1.3.3", features = ["v4", "serde"] }
[dependencies.attohttpc]
version = "0.22"
default-features = false
features = [ "tls-rustls" ]
[dependencies.rouille]
version = "3.6"
default-features = false

View file

@ -43,6 +43,40 @@ impl Record {
}
}
fn validate_captcha(token: &str) -> Result<()> {
// TODO(tazjin): pass `ip` parameter
let url = "https://smartcaptcha.yandexcloud.net/validate";
let backend_key =
env::var("YANDEX_SMARTCAPTCHA_KEY").context("captcha verification key not provided")?;
#[derive(Deserialize)]
struct CaptchaResponse {
status: String,
message: String,
}
let response: CaptchaResponse = attohttpc::get(url)
.param("secret", backend_key)
.param("token", token)
.send()
.context("failed to send captcha verification request")?
.error_for_status()
.context("captcha verification request failed")?
.json()
.context("failed to deserialize captcha verification response")?;
if response.status != "ok" {
warn!(
"invalid captcha: {} ({})",
response.message, response.status
);
}
info!("captcha token was valid");
Ok(())
}
fn persist_record(ip: &SocketAddr, record: &Record) -> Result<()> {
let bucket_name = "rih-backend-data";
let credentials =
@ -88,6 +122,8 @@ fn handle_submit(req: &Request) -> Result<Response> {
let submitted: FrontendReq =
rouille::input::json::json_input(req).context("failed to deserialise frontend request")?;
validate_captcha(&submitted.captcha_token)?;
if !submitted.record.validate() {
bail!("invalid record: {:?}", submitted.record);
}