trustcaptcha_rust/
captcha_manager.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::aes_encryption::AesEncryption;
use crate::model::verification_result::VerificationResult;
use crate::model::verification_token::VerificationToken;
use base64::{engine::general_purpose, Engine as _};
use reqwest::Client;
use std::error::Error;

pub struct CaptchaManager;

impl CaptchaManager {
    pub async fn get_verification_result(
        base64_secret_key: &str,
        base64_verification_token: &str,
    ) -> Result<VerificationResult, Box<dyn Error>> {
        let verification_token = CaptchaManager::get_verification_token(base64_verification_token)?;
        let decrypted_access_token =
            CaptchaManager::decrypt_access_token(base64_secret_key, &verification_token)?;
        CaptchaManager::fetch_verification_result(&verification_token, &decrypted_access_token)
            .await
    }

    fn get_verification_token(
        base64_verification_token: &str,
    ) -> Result<VerificationToken, Box<dyn Error>> {
        let decoded_token = general_purpose::STANDARD.decode(base64_verification_token)?;
        let decoded_str = String::from_utf8(decoded_token)?;
        let verification_token: VerificationToken = serde_json::from_str(&decoded_str)?;
        Ok(verification_token)
    }

    fn decrypt_access_token(
        base64_secret_key: &str,
        verification_token: &VerificationToken,
    ) -> Result<String, Box<dyn Error>> {
        let secret_key = AesEncryption::to_aes_secret_key(base64_secret_key);
        let decrypted_access_token = AesEncryption::decrypt_to_string(
            &secret_key,
            &verification_token.encrypted_access_token,
        );
        Ok(decrypted_access_token)
    }

    async fn fetch_verification_result(
        verification_token: &VerificationToken,
        access_token: &str,
    ) -> Result<VerificationResult, Box<dyn Error>> {
        let url = format!(
            "{}/verifications/{}/assessments?accessToken={}&pl=rs",
            verification_token.api_endpoint, verification_token.verification_id, access_token
        );
        let client = Client::new();
        let response = client.get(&url).send().await?;
        if response.status().is_success() {
            let verification_result: VerificationResult = response.json().await?;
            Ok(verification_result)
        } else {
            Err(Box::new(VerificationNotFoundError))
        }
    }
}

#[derive(Debug)]
struct VerificationNotFoundError;

impl std::fmt::Display for VerificationNotFoundError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Verification not found")
    }
}

impl Error for VerificationNotFoundError {}