Merge pull request #202 from JVMerkle/bugfix/cal-color-validation

This commit is contained in:
Dionisio Pozo
2026-03-14 16:35:57 +01:00
committed by GitHub
+80 -36
View File
@@ -82,24 +82,8 @@ impl Calendar {
)); ));
} }
// Validate color format if provided (#RRGGBB) if let Some(color_str) = &color {
if let Some(ref color_str) = color { Self::validate_color(color_str)?;
if !color_str.starts_with('#') || color_str.len() != 7 {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"Calendar",
"Color must be in #RRGGBB format",
));
}
// Check if remaining characters are valid hex
if color_str[1..].chars().any(|c| !c.is_ascii_hexdigit()) {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"Calendar",
"Color must be in #RRGGBB format with valid hex digits",
));
}
} }
let now = Utc::now(); let now = Utc::now();
@@ -155,6 +139,10 @@ impl Calendar {
)); ));
} }
if let Some(color_str) = &color {
Self::validate_color(color_str)?;
}
Ok(Self { Ok(Self {
id, id,
name, name,
@@ -253,24 +241,9 @@ impl Calendar {
* @return Result indicating success or containing a domain error * @return Result indicating success or containing a domain error
*/ */
pub fn update_color(&mut self, color: Option<String>) -> Result<()> { pub fn update_color(&mut self, color: Option<String>) -> Result<()> {
// Validate color format if provided (#RRGGBB) // Validate color format if provided
if let Some(ref color_str) = color { if let Some(color_str) = &color {
if !color_str.starts_with('#') || color_str.len() != 7 { Self::validate_color(&color_str)?;
return Err(DomainError::new(
ErrorKind::InvalidInput,
"Calendar",
"Color must be in #RRGGBB format",
));
}
// Check if remaining characters are valid hex
if color_str[1..].chars().any(|c| !c.is_ascii_hexdigit()) {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"Calendar",
"Color must be in #RRGGBB format with valid hex digits",
));
}
} }
self.color = color; self.color = color;
@@ -278,6 +251,21 @@ impl Calendar {
Ok(()) Ok(())
} }
/// Validate a calendar color
fn validate_color(color: &str) -> Result<()> {
if !color.starts_with('#')
|| !(color.len() == 7 || color.len() == 9)
|| color[1..].chars().any(|c| !c.is_ascii_hexdigit())
{
return Err(DomainError::new(
ErrorKind::InvalidInput,
"Calendar",
"Color must be in #RRGGBB or #RRGGBBAA format",
));
}
Ok(())
}
/** /**
* Sets a custom property for extended CalDAV support. * Sets a custom property for extended CalDAV support.
* *
@@ -321,3 +309,59 @@ impl Calendar {
self.updated_at = Utc::now(); self.updated_at = Utc::now();
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_init() {
let res = Calendar::new("Name".to_string(), "ID".to_string(), None, None);
assert!(res.is_ok());
}
#[test]
fn test_init_color_rgb() {
let res = Calendar::new(
"Name".to_string(),
"ID".to_string(),
None,
Some("#84FFa9".to_string()),
);
assert!(res.is_ok());
}
/// Format as used by the android DAVx app
#[test]
fn test_init_color_rgba() {
let res = Calendar::new(
"Name".to_string(),
"ID".to_string(),
None,
Some("#abcdef51".to_string()),
);
assert!(res.is_ok());
}
#[test]
fn test_init_bad_color_1() {
let res = Calendar::new(
"Name".to_string(),
"ID".to_string(),
None,
Some("foo".to_string()),
);
assert!(res.is_err());
}
#[test]
fn test_init_bad_color_2() {
let res = Calendar::new(
"Name".to_string(),
"ID".to_string(),
None,
Some("#xxjjff".to_string()),
);
assert!(res.is_err());
}
}