1
0
Fork 0
forked from TWS/kalkutago

Add client dir, move .git from server to parent dir

This commit is contained in:
D. Scott Boggs 2023-06-11 07:01:57 -04:00
parent b8b0e51046
commit f794f5c974
41 changed files with 757 additions and 7 deletions

31
server/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()
}
}

71
server/src/api/groups.rs Normal file
View file

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

44
server/src/api/mod.rs Normal file
View file

@ -0,0 +1,44 @@
mod error;
mod groups;
mod ticks;
mod tracks;
use std::default::default;
use std::net::{IpAddr, Ipv4Addr};
use rocket::Config;
use sea_orm::DatabaseConnection;
use crate::rocket::{Build, Rocket};
pub(crate) use error::ErrorResponder;
#[get("/status")]
fn status() -> &'static str {
"Ok"
}
pub(crate) fn start_server(db: DatabaseConnection) -> Rocket<Build> {
use groups::*;
use ticks::*;
use tracks::*;
rocket::build()
.configure(Config {
address: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
..default()
})
.manage(db)
.mount("/api/v1", routes![status])
.mount(
"/api/v1/tracks",
routes![all_tracks, track, insert_track, update_track, delete_track],
)
.mount(
"/api/v1/ticks",
routes![all_ticks, tick, insert_tick, update_tick, delete_tick],
)
.mount(
"/api/v1/groups",
routes![all_groups, group, insert_group, update_group, delete_group],
)
}

68
server/src/api/ticks.rs Normal file
View file

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

69
server/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};
use std::default::default;
#[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 mut track = track.0;
let db = db as &DatabaseConnection;
let mut model: tracks::ActiveModel = default();
track["id"] = 0.into(); // dummy value. set_from_json doesn't use this value
// but for some reason requires it be set
model.set_from_json(track).map_err(Error::from)?;
Ok(Json(model.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)
}