Browse Source

Do not panic on a malformed Public API event date

parse_date() unwraps the RFC 3339 parse, so a malformed start, end or
continuationToken in a /public/events request panicked the handler and returned
a 500. These values come straight from the query string.

Adds parse_date_checked(), which returns None instead of panicking, and uses it
for the three client supplied dates so an invalid one is reported as a normal
error response. parse_date() keeps its previous behaviour for existing callers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pull/7570/head
Rune Darrud 5 days ago
parent
commit
bc491e9830
  1. 15
      src/api/core/public.rs
  2. 8
      src/util.rs

15
src/api/core/public.rs

@ -20,7 +20,7 @@ use crate::{
}, },
}, },
mail, mail,
util::parse_date, util::parse_date_checked,
}; };
use super::events::{EventRange, get_continuation_token}; 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. // Return an empty vec when the org events are disabled.
// This prevents client errors // This prevents client errors
let events_json: Vec<Value> = if CONFIG.org_events_enabled() { let events_json: Vec<Value> = if CONFIG.org_events_enabled() {
let start_date = parse_date(&data.start); // These come straight from the query string, so they must not be parsed with
let end_date = if let Some(before_date) = &data.continuation_token { // parse_date(), which panics on anything that is not a valid RFC 3339 date.
parse_date(before_date) let Some(start_date) = parse_date_checked(&data.start) else {
} else { err!("Invalid start date")
parse_date(&data.end) };
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) Event::find_by_organization_uuid(&org_id, &start_date, &end_date, &conn)

8
src/util.rs

@ -485,7 +485,13 @@ pub fn format_datetime_http(dt: &DateTime<Local>) -> String {
} }
pub fn parse_date(date: &str) -> NaiveDateTime { 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<NaiveDateTime> {
DateTime::parse_from_rfc3339(date).ok().map(|d| d.naive_utc())
} }
/// Returns true or false if an email address is valid or not /// Returns true or false if an email address is valid or not

Loading…
Cancel
Save