Files
tuliprox/shared/src/model/config/ipcheck.rs
T
2025-12-26 14:09:44 +01:00

89 lines
2.9 KiB
Rust

use crate::error::{TuliproxError, TuliproxErrorKind};
use crate::utils::is_blank_optional_string;
use regex::Regex;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct IpCheckConfigDto {
/// URL that may return both IPv4 and IPv6 in one response
#[serde(default)]
pub url: Option<String>,
/// Dedicated URL to fetch only IPv4
#[serde(default)]
pub url_ipv4: Option<String>,
/// Dedicated URL to fetch only IPv6
#[serde(default)]
pub url_ipv6: Option<String>,
/// Optional regex pattern to extract IPv4
#[serde(default)]
pub pattern_ipv4: Option<String>,
/// Optional regex pattern to extract IPv6
#[serde(default)]
pub pattern_ipv6: Option<String>,
}
impl IpCheckConfigDto {
pub fn is_empty(&self) -> bool {
is_blank_optional_string(self.url.as_ref())
&& is_blank_optional_string(self.url_ipv4.as_ref())
&& is_blank_optional_string(self.url_ipv6.as_ref())
&& is_blank_optional_string(self.pattern_ipv4.as_ref())
&& is_blank_optional_string(self.pattern_ipv6.as_ref())
}
pub fn clean(&mut self) {
let norm = |s: &mut Option<String>| {
if let Some(val) = s.as_mut() {
let trimmed = val.trim();
if trimmed.is_empty() {
*s = None;
} else if trimmed.len() != val.len() {
*val = trimmed.to_owned();
}
}
};
norm(&mut self.url);
norm(&mut self.url_ipv4);
norm(&mut self.url_ipv6);
norm(&mut self.pattern_ipv4);
norm(&mut self.pattern_ipv6);
}
pub fn prepare(&mut self) -> Result<(), TuliproxError> {
self.clean();
if self.url.is_none() && self.url_ipv4.is_none() && self.url_ipv6.is_none() {
return Err(TuliproxError::new(
TuliproxErrorKind::Info,
"No url provided!".to_owned(),
));
}
// TODO allow or do not allow ?
// if self.url.is_some() && (self.url_ipv4.is_some() || self.url_ipv6.is_some()) {
// return Err(TuliproxError::new(TuliproxErrorKind::Info, "url in combination with ipv4 and/or ipv6 url not allowed!".to_owned()));
// }
if let Some(p4) = &self.pattern_ipv4 {
Regex::new(p4).map_err(|err| {
TuliproxError::new(
TuliproxErrorKind::Info,
format!("Invalid IPv4 regex: {p4} {err}"),
)
})?;
}
if let Some(p6) = &self.pattern_ipv6 {
Regex::new(p6).map_err(|err| {
TuliproxError::new(
TuliproxErrorKind::Info,
format!("Invalid IPv6 regex: {p6} {err}"),
)
})?;
}
Ok(())
}
}