Renamed directories
This commit is contained in:
5
service/src/airports/mod.rs
Normal file
5
service/src/airports/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod model;
|
||||
mod routes;
|
||||
|
||||
pub use model::*;
|
||||
pub use routes::init_routes;
|
||||
108
service/src/airports/model.rs
Normal file
108
service/src/airports/model.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use crate::db;
|
||||
use crate::error_handler::ServiceError;
|
||||
use crate::schema::airports;
|
||||
use diesel::prelude::*;
|
||||
// use log::trace;
|
||||
use postgis_diesel::types::*;
|
||||
use postgis_diesel::functions::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, AsChangeset, Insertable)]
|
||||
#[diesel(table_name = airports)]
|
||||
pub struct InsertAirport {
|
||||
pub icao: String,
|
||||
pub category: String,
|
||||
pub full_name: String,
|
||||
pub elevation_ft: Option<i32>,
|
||||
pub continent: String,
|
||||
pub iso_country: String,
|
||||
pub iso_region: String,
|
||||
pub municipality: String,
|
||||
pub gps_code: String,
|
||||
pub iata_code: String,
|
||||
pub local_code: String,
|
||||
pub point: Point
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Queryable, QueryableByName)]
|
||||
#[diesel(table_name = airports)]
|
||||
pub struct QueryAirport {
|
||||
pub icao: String,
|
||||
pub id: i32,
|
||||
pub category: String,
|
||||
pub full_name: String,
|
||||
pub elevation_ft: Option<i32>,
|
||||
pub continent: String,
|
||||
pub iso_country: String,
|
||||
pub iso_region: String,
|
||||
pub municipality: String,
|
||||
pub gps_code: String,
|
||||
pub iata_code: String,
|
||||
pub local_code: String,
|
||||
pub point: Point
|
||||
}
|
||||
|
||||
impl QueryAirport {
|
||||
pub fn get_all(bounds: Option<Polygon<Point>>, category: Option<String>, filter: Option<String>, limit: Option<i32>, page: Option<i32>) -> Result<Vec<Self>, ServiceError> {
|
||||
let mut conn = db::connection()?;
|
||||
let limit = match limit {
|
||||
Some(l) => l,
|
||||
None => 100
|
||||
};
|
||||
let page = match page {
|
||||
Some(p) => p,
|
||||
None => 1
|
||||
};
|
||||
let mut query = airports::table
|
||||
.limit(limit as i64)
|
||||
.into_boxed();
|
||||
query = query.filter(airports::id.gt(std::cmp::max(1, page - 1) * limit));
|
||||
|
||||
if let Some(bounds) = bounds {
|
||||
query = query.filter(st_contains(bounds, airports::point));
|
||||
}
|
||||
if let Some(category) = category {
|
||||
query = query.filter(airports::category.eq(category));
|
||||
}
|
||||
if let Some(filter) = filter {
|
||||
query = query.filter(airports::icao
|
||||
.ilike(format!("%{}%", filter))
|
||||
.or(airports::full_name.ilike(format!("%{}%", filter)))
|
||||
)
|
||||
}
|
||||
// let debug = diesel::debug_query::<diesel::pg::Pg, _>(&query);
|
||||
// trace!("{}", debug);
|
||||
let airports: Vec<QueryAirport> = query.order(airports::category.asc()).load::<QueryAirport>(&mut conn)?;
|
||||
Ok(airports)
|
||||
}
|
||||
|
||||
pub fn find(icao: String) -> Result<Self, ServiceError> {
|
||||
let mut conn = db::connection()?;
|
||||
let airport = airports::table.filter(airports::icao.eq(icao)).first(&mut conn)?;
|
||||
Ok(airport)
|
||||
}
|
||||
|
||||
pub fn create(airport: InsertAirport) -> Result<Self, ServiceError> {
|
||||
let mut conn = db::connection()?;
|
||||
let airport = InsertAirport::from(airport);
|
||||
let airport = diesel::insert_into(airports::table)
|
||||
.values(airport)
|
||||
.get_result(&mut conn)?;
|
||||
Ok(airport)
|
||||
}
|
||||
|
||||
pub fn update(id: i32, airport: InsertAirport) -> Result<Self, ServiceError> {
|
||||
let mut conn = db::connection()?;
|
||||
let airport = diesel::update(airports::table)
|
||||
.filter(airports::id.eq(id))
|
||||
.set(airport)
|
||||
.get_result(&mut conn)?;
|
||||
Ok(airport)
|
||||
}
|
||||
|
||||
pub fn delete(id: i32) -> Result<usize, ServiceError> {
|
||||
let mut conn = db::connection()?;
|
||||
let res = diesel::delete(airports::table.filter(airports::id.eq(id))).execute(&mut conn)?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
157
service/src/airports/routes.rs
Normal file
157
service/src/airports/routes.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
use crate::{airports::{InsertAirport, QueryAirport}, db::{self, Metadata}};
|
||||
use actix_web::{delete, get, post, put, web, HttpResponse, HttpRequest};
|
||||
use log::{error, warn};
|
||||
use postgis_diesel::types::{Polygon, Point};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct GetAllParameters {
|
||||
filter: Option<String>,
|
||||
bounds: Option<String>,
|
||||
category: Option<String>,
|
||||
limit: Option<i32>,
|
||||
page: Option<i32>
|
||||
}
|
||||
|
||||
#[get("/import")]
|
||||
async fn import() -> HttpResponse {
|
||||
db::import_data();
|
||||
HttpResponse::Ok().body({})
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AirportsResponse {
|
||||
pub data: Vec<QueryAirport>,
|
||||
pub meta: Metadata
|
||||
}
|
||||
|
||||
#[get("/airports")]
|
||||
async fn get_all(req: HttpRequest) -> HttpResponse {
|
||||
let params = web::Query::<GetAllParameters>::from_query(req.query_string()).unwrap();
|
||||
let polygon: Option<Polygon<Point>> = match ¶ms.bounds {
|
||||
Some(b) => {
|
||||
let bounds: Vec<&str> = b.split(",").collect();
|
||||
if bounds.len() != 4 {
|
||||
warn!("Expected 4 bounds, received {}: {}", bounds.len(), b);
|
||||
return HttpResponse::UnprocessableEntity().body(format!("Received {}; expected NE_LAT,NE_LON,SW_LAT,SW_LON", b))
|
||||
}
|
||||
let ne_lat = match bounds[0].parse::<f64>() {
|
||||
Ok(b) => b,
|
||||
Err(err) => {
|
||||
warn!("{}", err);
|
||||
return HttpResponse::UnprocessableEntity().body(format!("{}", err))
|
||||
}
|
||||
};
|
||||
let ne_lon = match bounds[1].parse::<f64>() {
|
||||
Ok(b) => b,
|
||||
Err(err) => {
|
||||
warn!("{}", err);
|
||||
return HttpResponse::UnprocessableEntity().body(format!("{}", err))
|
||||
}
|
||||
};
|
||||
let sw_lat = match bounds[2].parse::<f64>() {
|
||||
Ok(b) => b,
|
||||
Err(err) => {
|
||||
warn!("{}", err);
|
||||
return HttpResponse::UnprocessableEntity().body(format!("{}", err))
|
||||
}
|
||||
};
|
||||
let sw_lon = match bounds[3].parse::<f64>() {
|
||||
Ok(b) => b,
|
||||
Err(err) => {
|
||||
warn!("{}", err);
|
||||
return HttpResponse::UnprocessableEntity().body(format!("{}", err))
|
||||
}
|
||||
};
|
||||
let mut polygon: Polygon<Point> = Polygon::new(Some(4326));
|
||||
polygon.add_point(Point { x: sw_lon, y: sw_lat, srid: Some(4326) });
|
||||
polygon.add_point(Point { x: ne_lon, y: sw_lat, srid: Some(4326) });
|
||||
polygon.add_point(Point { x: ne_lon, y: ne_lat, srid: Some(4326) });
|
||||
polygon.add_point(Point { x: sw_lon, y: ne_lat, srid: Some(4326) });
|
||||
polygon.add_point(Point { x: sw_lon, y: sw_lat, srid: Some(4326) });
|
||||
Some(polygon)
|
||||
},
|
||||
None => None
|
||||
};
|
||||
let category = match ¶ms.category {
|
||||
Some(c) => Some(c.to_string()),
|
||||
None => None
|
||||
};
|
||||
let filter = match ¶ms.filter {
|
||||
Some(f) => Some(f.to_string()),
|
||||
None => None
|
||||
};
|
||||
|
||||
match web::block(move || QueryAirport::get_all(polygon, category, filter, params.limit, params.page)).await.unwrap() {
|
||||
Ok(a) => HttpResponse::Ok().json(AirportsResponse {
|
||||
data: a,
|
||||
meta: Metadata { page: 0, limit: 0, pages: 0, total: 0 }
|
||||
}),
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
err.to_http_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AirportResponse {
|
||||
pub data: QueryAirport,
|
||||
pub meta: Metadata
|
||||
}
|
||||
|
||||
#[get("/airports/{icao}")]
|
||||
async fn get(icao: web::Path<String>) -> HttpResponse {
|
||||
match QueryAirport::find(icao.into_inner()) {
|
||||
Ok(a) => HttpResponse::Ok().json(AirportResponse {
|
||||
data: a,
|
||||
meta: Metadata { page: 0, limit: 0, pages: 0, total: 0 }
|
||||
}),
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
err.to_http_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/airports")]
|
||||
async fn create(airport: web::Json<InsertAirport>) -> HttpResponse {
|
||||
match QueryAirport::create(airport.into_inner()) {
|
||||
Ok(a) => HttpResponse::Created().json(a),
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
err.to_http_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[put("/airports/{icao}")]
|
||||
async fn update(icao: web::Path<i32>, airport: web::Json<InsertAirport>) -> HttpResponse {
|
||||
match QueryAirport::update(icao.into_inner(), airport.into_inner()) {
|
||||
Ok(a) => HttpResponse::Ok().json(a),
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
err.to_http_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[delete("/airports/{icao}")]
|
||||
async fn delete(icao: web::Path<i32>) -> HttpResponse {
|
||||
match QueryAirport::delete(icao.into_inner()) {
|
||||
Ok(_) => HttpResponse::NoContent().finish(),
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
err.to_http_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_routes(config: &mut web::ServiceConfig) {
|
||||
config.service(get_all);
|
||||
config.service(get);
|
||||
config.service(create);
|
||||
config.service(update);
|
||||
config.service(delete);
|
||||
config.service(import);
|
||||
}
|
||||
Reference in New Issue
Block a user