diff --git a/src/api/core/public.rs b/src/api/core/public.rs index f8fd1c2a..a815c76c 100644 --- a/src/api/core/public.rs +++ b/src/api/core/public.rs @@ -20,7 +20,7 @@ use crate::{ }, }, mail, - util::parse_date, + util::parse_date_checked, }; use super::events::{EventRange, get_continuation_token}; @@ -211,11 +211,14 @@ async fn get_events(data: EventRange, token: PublicToken, conn: DbConn) -> JsonR // Return an empty vec when the org events are disabled. // This prevents client errors let events_json: Vec = if CONFIG.org_events_enabled() { - let start_date = parse_date(&data.start); - let end_date = if let Some(before_date) = &data.continuation_token { - parse_date(before_date) - } else { - parse_date(&data.end) + // These come straight from the query string, so they must not be parsed with + // parse_date(), which panics on anything that is not a valid RFC 3339 date. + let Some(start_date) = parse_date_checked(&data.start) else { + err!("Invalid start date") + }; + let end = data.continuation_token.as_deref().unwrap_or(&data.end); + let Some(end_date) = parse_date_checked(end) else { + err!("Invalid end date") }; Event::find_by_organization_uuid(&org_id, &start_date, &end_date, &conn) diff --git a/src/util.rs b/src/util.rs index 91f075d1..d6ceb202 100644 --- a/src/util.rs +++ b/src/util.rs @@ -485,7 +485,13 @@ pub fn format_datetime_http(dt: &DateTime) -> String { } pub fn parse_date(date: &str) -> NaiveDateTime { - DateTime::parse_from_rfc3339(date).unwrap().naive_utc() + parse_date_checked(date).unwrap() +} + +/// Parses an RFC 3339 date, returning None instead of panicking when the input is not a +/// valid date. Use this for dates that come straight from a request. +pub fn parse_date_checked(date: &str) -> Option { + DateTime::parse_from_rfc3339(date).ok().map(|d| d.naive_utc()) } /// Returns true or false if an email address is valid or not