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