Add tracks routes

This commit is contained in:
D. Scott Boggs 2023-06-08 07:49:46 -04:00
parent d0635bc4c5
commit 3203a3fd70
7 changed files with 133 additions and 7 deletions

7
Cargo.lock generated
View file

@ -522,6 +522,9 @@ name = "either"
version = "1.8.1" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
@ -997,9 +1000,12 @@ name = "kalkulog-server"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"derive_builder", "derive_builder",
"either",
"rocket", "rocket",
"sea-orm", "sea-orm",
"sea-orm-migration", "sea-orm-migration",
"serde",
"serde_json",
"thiserror", "thiserror",
"tokio", "tokio",
] ]
@ -1603,6 +1609,7 @@ dependencies = [
"rocket_codegen", "rocket_codegen",
"rocket_http", "rocket_http",
"serde", "serde",
"serde_json",
"state", "state",
"tempfile", "tempfile",
"time", "time",

View file

@ -10,6 +10,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
sea-orm-migration = "0.11.3" sea-orm-migration = "0.11.3"
serde_json = "1.0.96"
thiserror = "1.0.40" thiserror = "1.0.40"
[dependencies.derive_builder] [dependencies.derive_builder]
@ -32,3 +33,12 @@ features = [
[dependencies.rocket] [dependencies.rocket]
git = "https://github.com/SergioBenitez/Rocket" git = "https://github.com/SergioBenitez/Rocket"
rev = "v0.5.0-rc.3" rev = "v0.5.0-rc.3"
features = ["json"]
[dependencies.serde]
version = "1.0.163"
features = ["derive"]
[dependencies.either]
version = "1.8.1"
features = ["serde"]

31
src/api/error.rs Normal file
View file

@ -0,0 +1,31 @@
use crate::error::Error;
#[derive(Responder)]
#[response(status = 500, content_type = "json")]
pub(crate) struct ErrorResponder {
message: String,
}
pub(crate) type ApiResult<T> = Result<T, ErrorResponder>;
// The following impl's are for easy conversion of error types.
impl From<Error> for ErrorResponder {
fn from(err: Error) -> ErrorResponder {
ErrorResponder {
message: err.to_string(),
}
}
}
impl From<String> for ErrorResponder {
fn from(string: String) -> ErrorResponder {
ErrorResponder { message: string }
}
}
impl From<&str> for ErrorResponder {
fn from(str: &str) -> ErrorResponder {
str.to_owned().into()
}
}

View file

@ -1,23 +1,31 @@
mod error;
mod tracks;
use std::default::default; use std::default::default;
use std::net::{IpAddr, Ipv4Addr}; use std::net::{IpAddr, Ipv4Addr};
use rocket::Config; use rocket::Config;
use sea_orm::DatabaseConnection;
use crate::{ use crate::rocket::{Build, Rocket};
entities::{prelude::*, *},
rocket::{Build, Rocket}, pub(crate) use error::ErrorResponder;
};
#[get("/status")] #[get("/status")]
fn status() -> &'static str { fn status() -> &'static str {
"Ok" "Ok"
} }
pub(crate) fn start_server() -> Rocket<Build> { pub(crate) fn start_server(db: DatabaseConnection) -> Rocket<Build> {
rocket::build() rocket::build()
.configure(Config { .configure(Config {
address: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), address: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
..default() ..default()
}) })
.manage(db)
.mount("/", routes![status]) .mount("/", routes![status])
.mount("/tracks", {
use tracks::*;
routes![all_tracks, track, insert_track, update_track, delete_track]
})
} }

69
src/api/tracks.rs Normal file
View file

@ -0,0 +1,69 @@
use crate::api::{self, error::ApiResult};
use crate::entities::{prelude::*, *};
use crate::error::Error;
use either::Either::{self, Left, Right};
use rocket::http::Status;
use rocket::{serde::json::Json, State};
use sea_orm::{prelude::*, DatabaseConnection};
#[get("/")]
pub(super) async fn all_tracks(
db: &State<DatabaseConnection>,
) -> ApiResult<Json<Vec<tracks::Model>>> {
let db = db as &DatabaseConnection;
let tracks = Tracks::find().all(db).await.unwrap();
Ok(Json(tracks))
}
#[get("/<id>")]
pub(super) async fn track(
db: &State<DatabaseConnection>,
id: i32,
) -> Result<Json<tracks::Model>, Either<Status, api::ErrorResponder>> {
let db = db as &DatabaseConnection;
match Tracks::find_by_id(id).one(db).await {
Ok(Some(track)) => Ok(Json(track)),
Ok(None) => Err(Left(Status::NotFound)),
Err(err) => Err(Right(Error::from(err).into())),
}
}
#[post("/", format = "application/json", data = "<track>")]
pub(super) async fn insert_track(
db: &State<DatabaseConnection>,
track: Json<serde_json::Value>,
) -> ApiResult<Json<tracks::Model>> {
let db = db as &DatabaseConnection;
Ok(Json(
tracks::ActiveModel::from_json(track.0)
.map_err(Error::from)?
.insert(db)
.await
.map_err(Error::from)?,
))
}
#[put("/", format = "application/json", data = "<track>")]
pub(super) async fn update_track(
db: &State<DatabaseConnection>,
track: Json<serde_json::Value>,
) -> ApiResult<Json<tracks::Model>> {
let db = db as &DatabaseConnection;
Ok(Json(
tracks::ActiveModel::from_json(track.0)
.map_err(Error::from)?
.update(db)
.await
.map_err(Error::from)?,
))
}
#[delete("/<id>")]
pub(super) async fn delete_track(db: &State<DatabaseConnection>, id: i32) -> ApiResult<Status> {
let db = db as &DatabaseConnection;
Tracks::delete_by_id(id)
.exec(db)
.await
.map_err(Error::from)?;
Ok(Status::Ok)
}

View file

@ -1,8 +1,9 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "tracks")] #[sea_orm(table_name = "tracks")]
pub struct Model { pub struct Model {
#[sea_orm(primary_key)] #[sea_orm(primary_key)]

View file

@ -32,5 +32,5 @@ async fn rocket_defines_the_main_fn() -> _ {
.has_table("track2_groups") .has_table("track2_groups")
.await .await
.expect("fetch track2groups table")); .expect("fetch track2groups table"));
api::start_server() api::start_server(db)
} }