pinakes-server: validate GPS coordinate bounds; validate saved search fields and sort_order
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Idca86117aeeff4afd489ee00bb5c70a36a6a6964
This commit is contained in:
parent
18fda530f2
commit
61eb2335d3
4 changed files with 51 additions and 0 deletions
|
|
@ -152,6 +152,14 @@ pub async fn get_map_photos(
|
|||
State(state): State<AppState>,
|
||||
Query(query): Query<MapQuery>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let valid_lat = |v: f64| v.is_finite() && (-90.0..=90.0).contains(&v);
|
||||
let valid_lon = |v: f64| v.is_finite() && (-180.0..=180.0).contains(&v);
|
||||
if !valid_lat(query.lat1) || !valid_lat(query.lat2) {
|
||||
return Err(ApiError::bad_request("latitude must be in [-90, 90]"));
|
||||
}
|
||||
if !valid_lon(query.lon1) || !valid_lon(query.lon2) {
|
||||
return Err(ApiError::bad_request("longitude must be in [-180, 180]"));
|
||||
}
|
||||
// Validate bounding box
|
||||
let min_lat = query.lat1.min(query.lat2);
|
||||
let max_lat = query.lat1.max(query.lat2);
|
||||
|
|
|
|||
|
|
@ -22,10 +22,43 @@ pub struct SavedSearchResponse {
|
|||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
const VALID_SORT_ORDERS: &[&str] = &[
|
||||
"date_asc",
|
||||
"date_desc",
|
||||
"name_asc",
|
||||
"name_desc",
|
||||
"size_asc",
|
||||
"size_desc",
|
||||
];
|
||||
|
||||
pub async fn create_saved_search(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<CreateSavedSearchRequest>,
|
||||
) -> Result<Json<SavedSearchResponse>, ApiError> {
|
||||
let name_len = req.name.chars().count();
|
||||
if name_len == 0 || name_len > 255 {
|
||||
return Err(ApiError(
|
||||
pinakes_core::error::PinakesError::InvalidOperation(
|
||||
"name must be 1-255 characters".into(),
|
||||
),
|
||||
));
|
||||
}
|
||||
if req.query.is_empty() || req.query.len() > 2048 {
|
||||
return Err(ApiError(
|
||||
pinakes_core::error::PinakesError::InvalidOperation(
|
||||
"query must be 1-2048 bytes".into(),
|
||||
),
|
||||
));
|
||||
}
|
||||
if let Some(ref sort) = req.sort_order
|
||||
&& !VALID_SORT_ORDERS.contains(&sort.as_str()) {
|
||||
return Err(ApiError(
|
||||
pinakes_core::error::PinakesError::InvalidOperation(format!(
|
||||
"sort_order must be one of: {}",
|
||||
VALID_SORT_ORDERS.join(", ")
|
||||
)),
|
||||
));
|
||||
}
|
||||
let id = uuid::Uuid::now_v7();
|
||||
state
|
||||
.storage
|
||||
|
|
|
|||
|
|
@ -47,6 +47,13 @@ pub async fn add_subtitle(
|
|||
),
|
||||
));
|
||||
}
|
||||
if req
|
||||
.language
|
||||
.as_ref()
|
||||
.is_some_and(|l| l.is_empty() || l.len() > 64)
|
||||
{
|
||||
return Err(ApiError::bad_request("language must be 1-64 bytes"));
|
||||
}
|
||||
let subtitle = Subtitle {
|
||||
id: Uuid::now_v7(),
|
||||
media_id: MediaId(id),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ pub async fn start_transcode(
|
|||
Path(id): Path<Uuid>,
|
||||
Json(req): Json<CreateTranscodeRequest>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
if req.profile.is_empty() || req.profile.len() > 255 {
|
||||
return Err(ApiError::bad_request("profile must be 1-255 bytes"));
|
||||
}
|
||||
let job_id = state
|
||||
.job_queue
|
||||
.submit(pinakes_core::jobs::JobKind::Transcode {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue