use schemars::JsonSchema;
use serde::{de::Error, Deserialize, Serialize};
use crate::ConfigurationSection;
#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, Serialize)]
pub enum CaptchaServiceKind {
#[serde(rename = "recaptcha_v2")]
RecaptchaV2,
#[serde(rename = "cloudflare_turnstile")]
CloudflareTurnstile,
#[serde(rename = "hcaptcha")]
HCaptcha,
}
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, Default)]
pub struct CaptchaConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub service: Option<CaptchaServiceKind>,
#[serde(skip_serializing_if = "Option::is_none")]
pub site_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secret_key: Option<String>,
}
impl CaptchaConfig {
pub(crate) fn is_default(&self) -> bool {
self.service.is_none() && self.site_key.is_none() && self.secret_key.is_none()
}
}
impl ConfigurationSection for CaptchaConfig {
const PATH: Option<&'static str> = Some("captcha");
fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
let metadata = figment.find_metadata(Self::PATH.unwrap());
let error_on_field = |mut error: figment::error::Error, field: &'static str| {
error.metadata = metadata.cloned();
error.profile = Some(figment::Profile::Default);
error.path = vec![Self::PATH.unwrap().to_owned(), field.to_owned()];
error
};
let missing_field = |field: &'static str| {
error_on_field(figment::error::Error::missing_field(field), field)
};
if let Some(CaptchaServiceKind::RecaptchaV2) = self.service {
if self.site_key.is_none() {
return Err(missing_field("site_key"));
}
if self.secret_key.is_none() {
return Err(missing_field("secret_key"));
}
}
Ok(())
}
}