huellas/src/routes.rs

124 lines
3.2 KiB
Rust
Raw Normal View History

use axum::extract::{Json, Path, State};
use axum::http::StatusCode;
use axum::routing::{delete, get};
use axum::Router;
use futures::TryStreamExt;
use sqlx::sqlite::SqlitePool;
2022-07-17 17:04:48 -04:00
// use rocket::fairing::{self, AdHoc};
2022-07-17 17:04:48 -04:00
use crate::place::Place;
type Result<T, E = (StatusCode, String)> = std::result::Result<T, E>;
2022-07-17 17:04:48 -04:00
fn internal_error<E>(err: E) -> (StatusCode, String)
where
E: std::error::Error,
{
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
}
2022-07-17 17:04:48 -04:00
async fn get_places(State(pool): State<SqlitePool>) -> Result<Json<Vec<Place>>> {
let places = ::sqlx::query!(
"SELECT id, name, address, open_hours, icon, description, url," +
2022-08-06 22:21:45 -04:00
r#"longitude as "longitude: f64", latitude as "latitude: f64" FROM places WHERE active = TRUE"#
)
.fetch(&pool)
2022-08-06 22:21:45 -04:00
.map_ok(|p| Place {
id: Some(p.id),
name: p.name,
address: p.address,
open_hours: p.open_hours,
icon: p.icon,
description: p.description,
latitude: p.latitude,
longitude: p.longitude,
url: p.url,
2022-08-06 22:21:45 -04:00
})
.try_collect::<Vec<_>>()
.await.map_err(internal_error)?;
2022-07-17 17:04:48 -04:00
Ok(Json(places))
}
async fn upsert_place(
State(pool): State<SqlitePool>,
Json(place): Json<Place>,
) -> Result<Json<Place>> {
if place.id.is_some() {
update_place(pool, place).await
} else {
insert_place(pool, place).await
}
}
struct Id {
id: i64,
}
async fn insert_place(pool: SqlitePool, mut place: Place) -> Result<Json<Place>> {
let i = ::sqlx::query_as!(
Id,
"INSERT INTO places (name, address, open_hours, icon, description, longitude, latitude, url)\
VALUES (?, ?, ?, ?, ?, ?, ?, ?)\
RETURNING id",
2022-07-17 17:04:48 -04:00
place.name,
place.address,
place.open_hours,
place.icon,
place.description,
place.longitude,
place.latitude,
place.url
2022-07-17 17:04:48 -04:00
)
.fetch_one(&pool)
.await
.map_err(internal_error)?;
2022-07-17 17:04:48 -04:00
place.id = Some(i.id);
Ok(Json(place))
2022-07-17 17:04:48 -04:00
}
async fn update_place(pool: SqlitePool, place: Place) -> Result<Json<Place>> {
let result = ::sqlx::query!(
"UPDATE places SET (name, address, open_hours, icon, description, longitude, latitude, url) = (?, ?, ?, ?, ?, ?, ?, ?) WHERE id = ?",
place.name,
place.address,
place.open_hours,
place.icon,
place.description,
place.longitude,
place.latitude,
place.url,
place.id,
)
.execute(&pool)
.await
.map_err(internal_error)?;
if result.rows_affected() == 1 {
Ok(Json(place))
} else {
Err((StatusCode::NOT_FOUND, "".to_owned()))
}
2022-07-17 17:04:48 -04:00
}
async fn delete_place(State(pool): State<SqlitePool>, Path(id): Path<i64>) -> Result<()> {
2022-07-17 17:04:48 -04:00
let result = ::sqlx::query!("UPDATE places SET active = FALSE WHERE id = ?", id)
.execute(&pool)
.await
.map_err(internal_error)?;
2022-07-17 17:04:48 -04:00
if result.rows_affected() == 1 {
Ok(())
} else {
Err((StatusCode::NOT_FOUND, "".to_owned()))
2022-07-17 17:04:48 -04:00
}
}
pub fn places_routes(pool: SqlitePool) -> Router {
Router::new()
.route("/", get(get_places).put(upsert_place))
.route("/:id", delete(delete_place))
.with_state(pool)
2022-07-17 17:04:48 -04:00
}