mas_templates/context/
captcha.rs1use std::sync::Arc;
8
9use minijinja::{
10 Value,
11 value::{Enumerator, Object},
12};
13use serde::Serialize;
14
15use crate::TemplateContext;
16
17#[derive(Debug)]
18struct CaptchaConfig(mas_data_model::CaptchaConfig);
19
20impl Object for CaptchaConfig {
21 fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
22 match key.as_str() {
23 Some("service") => Some(match &self.0.service {
24 mas_data_model::CaptchaService::RecaptchaV2 => "recaptcha_v2".into(),
25 mas_data_model::CaptchaService::CloudflareTurnstile => {
26 "cloudflare_turnstile".into()
27 }
28 mas_data_model::CaptchaService::HCaptcha => "hcaptcha".into(),
29 }),
30 Some("site_key") => Some(self.0.site_key.clone().into()),
31 _ => None,
32 }
33 }
34
35 fn enumerate(self: &Arc<Self>) -> Enumerator {
36 Enumerator::Str(&["service", "site_key"])
37 }
38}
39
40#[derive(Serialize)]
42pub struct WithCaptcha<T> {
43 captcha: Option<Value>,
44
45 #[serde(flatten)]
46 inner: T,
47}
48
49impl<T> WithCaptcha<T> {
50 #[must_use]
51 pub(crate) fn new(captcha: Option<mas_data_model::CaptchaConfig>, inner: T) -> Self {
52 Self {
53 captcha: captcha.map(|captcha| Value::from_object(CaptchaConfig(captcha))),
54 inner,
55 }
56 }
57}
58
59impl<T: TemplateContext> TemplateContext for WithCaptcha<T> {
60 fn sample(
61 now: chrono::DateTime<chrono::prelude::Utc>,
62 rng: &mut impl rand::prelude::Rng,
63 ) -> Vec<Self>
64 where
65 Self: Sized,
66 {
67 let inner = T::sample(now, rng);
68 inner
69 .into_iter()
70 .map(|inner| Self::new(None, inner))
71 .collect()
72 }
73}