diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 3 | ||||
| -rw-r--r-- | src/models/auth.rs | 2 | ||||
| -rw-r--r-- | src/models/mod.rs | 1 | ||||
| -rw-r--r-- | src/models/model.rs | 105 | ||||
| -rw-r--r-- | src/routes/mod.rs | 1 | ||||
| -rw-r--r-- | src/routes/model.rs | 39 |
6 files changed, 149 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index 4a211fd..1c9d63a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,8 @@ async fn create_app() -> Router { let api_routes = Router::new() .nest("/users", routes::user::create_route()) - .nest("/auth", routes::auth::create_route()); + .nest("/auth", routes::auth::create_route()) + .nest("/models", routes::model::create_route()); Router::new() // Map all routes to `/v1/*` namespace diff --git a/src/models/auth.rs b/src/models/auth.rs index 7f9ae00..4453bc7 100644 --- a/src/models/auth.rs +++ b/src/models/auth.rs @@ -18,7 +18,7 @@ struct Keys { #[derive(Serialize, Deserialize)] pub struct Claims { /// ID from the user model - user_id: i32, + pub user_id: i32, /// Expiration timestamp exp: usize, } diff --git a/src/models/mod.rs b/src/models/mod.rs index f9bae3d..7e61662 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,2 +1,3 @@ pub mod auth; +pub mod model; pub mod user; diff --git a/src/models/model.rs b/src/models/model.rs new file mode 100644 index 0000000..1fe9b61 --- /dev/null +++ b/src/models/model.rs @@ -0,0 +1,105 @@ +use crate::db::get_client; +use crate::errors::AppError; + +use chrono::{Local, NaiveDateTime}; +use serde::{Deserialize, Serialize}; +use validator::Validate; + +/// Model for models. +#[derive(Deserialize, Serialize, Validate)] +pub struct Model { + id: i32, + #[validate(length(min = 2, message = "Can not be empty"))] + name: String, + description: Option<String>, + duration: i32, + height: i32, + weight: i32, + printer: Option<String>, + material: Option<String>, + author_id: i32, + created: NaiveDateTime, + updated: NaiveDateTime, +} + +/// Payload used for model creation +#[derive(Deserialize)] +pub struct ModelCreate { + pub name: String, + pub description: Option<String>, + pub duration: i32, + pub height: i32, + pub weight: i32, + pub printer: Option<String>, + pub material: Option<String>, +} + +impl Model { + pub fn new( + name: String, + description: Option<String>, + duration: i32, + height: i32, + weight: i32, + printer: Option<String>, + material: Option<String>, + author_id: i32, + ) -> Self { + let now = Local::now().naive_utc(); + Self { + id: 0, + name, + description, + duration, + height, + weight, + printer, + material, + author_id, + created: now, + updated: now, + } + } + + /// Create a new model + pub async fn create(model: Model) -> Result<Model, AppError> { + let pool = unsafe { get_client() }; + + model + .validate() + .map_err(|error| AppError::BadRequest(error.to_string()))?; + + let rec = sqlx::query_as!( + Model, + r#" + INSERT INTO models (name, description, duration, height, weight, printer, material, author_id, created, updated) + VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10) + RETURNING * + "#, + model.name, + model.description, + model.duration, + model.height, + model.weight, + model.printer, + model.material, + model.author_id, + model.created, + model.updated, + ) + .fetch_one(pool) + .await?; + + Ok(rec) + } + + /// List all models + pub async fn list() -> Result<Vec<Model>, AppError> { + let pool = unsafe { get_client() }; + let rows = sqlx::query_as!(Model, r#"SELECT * FROM models"#) + .fetch_all(pool) + .await?; + + Ok(rows) + } +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index f9bae3d..7e61662 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,2 +1,3 @@ pub mod auth; +pub mod model; pub mod user; diff --git a/src/routes/model.rs b/src/routes/model.rs new file mode 100644 index 0000000..b1d4cc2 --- /dev/null +++ b/src/routes/model.rs @@ -0,0 +1,39 @@ +use crate::errors::AppError; +use crate::models::{ + auth::Claims, + model::{Model, ModelCreate}, +}; +use axum::{routing::get, Json, Router}; + +/// Create routes for `/v1/models/` namespace +pub fn create_route() -> Router { + Router::new().route("/", get(list_models).post(create_model)) +} + +/// List models. +async fn list_models() -> Result<Json<Vec<Model>>, AppError> { + let models = Model::list().await?; + + Ok(Json(models)) +} + +/// Create a model. Checks Authorization token +async fn create_model( + Json(payload): Json<ModelCreate>, + claims: Claims, +) -> Result<Json<Model>, AppError> { + let model = Model::new( + payload.name, + payload.description, + payload.duration, + payload.height, + payload.weight, + payload.printer, + payload.material, + claims.user_id, + ); + + let model_new = Model::create(model).await?; + + Ok(Json(model_new)) +} |
