use axum::http::StatusCode; use axum::response::IntoResponse; use serde_json::json; use crate::auth::PocketBaseUser; use crate::consts::FREE_ZONE_BOUNDS; /// Check whether the user is allowed to query data at the given bounds. /// Licensed users and admins bypass the check entirely. /// Free/anonymous users get 403 if bounds exceed the free zone. #[allow(clippy::result_large_err)] pub fn check_license_bounds( user: &Option, bounds: (f64, f64, f64, f64), ) -> Result<(), axum::response::Response> { if let Some(u) = user { if u.is_admin || u.subscription == "licensed" { return Ok(()); } } let (south, west, north, east) = bounds; let (fz_south, fz_west, fz_north, fz_east) = FREE_ZONE_BOUNDS; if south >= fz_south && west >= fz_west && north <= fz_north && east <= fz_east { return Ok(()); } let body = json!({ "error": "license_required", "message": "A license is required to view data outside the demo area", "free_zone": { "south": fz_south, "west": fz_west, "north": fz_north, "east": fz_east, } }); Err((StatusCode::FORBIDDEN, axum::Json(body)).into_response()) } /// Convenience wrapper that takes a point (lat, lon) instead of bounds. #[allow(clippy::result_large_err)] pub fn check_license_point( user: &Option, lat: f64, lon: f64, ) -> Result<(), axum::response::Response> { check_license_bounds(user, (lat, lon, lat, lon)) }