fix: validate cafe URL scheme on create and update
Make is_valid_url_scheme pub(crate) and use it to filter cafe website URLs on both create and update, matching roaster validation behavior. Add UpdateCafe::normalize() method for consistent sanitization.
This commit is contained in:
parent
b5d5949adf
commit
ff2c602139
3 changed files with 22 additions and 2 deletions
|
|
@ -192,6 +192,7 @@ pub(crate) async fn update_cafe(
|
|||
) -> Result<Response, ApiError> {
|
||||
let (submission, source) = payload.into_parts();
|
||||
let (update, image_data_url) = submission.into_parts();
|
||||
let update = update.normalize();
|
||||
|
||||
validate_update(&update, image_data_url.as_ref())?;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::domain::ids::CafeId;
|
||||
use crate::domain::listing::{SortDirection, SortKey};
|
||||
use crate::domain::roasters::is_valid_url_scheme;
|
||||
use crate::domain::timeline::{NewTimelineEvent, TimelineEventDetail};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -62,7 +63,8 @@ impl NewCafe {
|
|||
self.name = self.name.trim().to_string();
|
||||
self.city = self.city.trim().to_string();
|
||||
self.country = self.country.trim().to_string();
|
||||
self.website = normalize_optional_field(self.website);
|
||||
self.website =
|
||||
normalize_optional_field(self.website).filter(|url| is_valid_url_scheme(url));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +96,23 @@ pub struct UpdateCafe {
|
|||
pub created_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl UpdateCafe {
|
||||
pub fn normalize(mut self) -> Self {
|
||||
self.website = self
|
||||
.website
|
||||
.and_then(|w| {
|
||||
let trimmed = w.trim().to_string();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(trimmed)
|
||||
}
|
||||
})
|
||||
.filter(|url| is_valid_url_scheme(url));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum CafeSortKey {
|
||||
CreatedAt,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ fn normalize_optional_field(value: Option<String>) -> Option<String> {
|
|||
|
||||
/// Returns `true` if the URL starts with `http://` or `https://`.
|
||||
/// Rejects `javascript:`, `data:`, and other potentially dangerous schemes.
|
||||
fn is_valid_url_scheme(url: &str) -> bool {
|
||||
pub(crate) fn is_valid_url_scheme(url: &str) -> bool {
|
||||
let lower = url.trim().to_lowercase();
|
||||
lower.starts_with("http://") || lower.starts_with("https://")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue