diff --git a/Cargo.toml b/Cargo.toml index 4a11b1f..fc0a918 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,14 @@ rocket = { version = "0.5.0-rc.1", features = [ ] } serde = "1.0.133" +[dependencies.uuid] +version = "1.1.2" +features = [ + "v4", # Lets you generate random UUIDs + "fast-rng", # Use a faster (but still sufficiently random) RNG + "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs +] + [dependencies.sea-orm] version = "^0.5.0" features = ["macros", "runtime-tokio-native-tls"] diff --git a/src/auth/auth_preflag_request_guard.rs b/src/auth/auth_preflag_request_guard.rs index 75152f2..1818f3f 100644 --- a/src/auth/auth_preflag_request_guard.rs +++ b/src/auth/auth_preflag_request_guard.rs @@ -25,21 +25,28 @@ impl<'r> FromRequest<'r> for AuthPreflag { .get(0) { Some(key) => key.to_string(), - None => return Outcome::Failure((Status::BadRequest, AuthError::Missing)), + + // 401 Unauthorized is sent due to that status code being used to signify you don't have authorization in your request + // None => return Outcome::Failure((Status::BadRequest, AuthError::Missing)), + None => return Outcome::Failure((Status::Unauthorized, AuthError::Missing)), }; let db = match req.guard::>().await { Success(db) => db.into_inner(), + + // 403 Forbidden is sent due to that status code being used to signify you don't have permission + // _ => return Outcome::Failure((Status::BadRequest, AuthError::Invalid)), _ => return Outcome::Failure((Status::BadRequest, AuthError::Invalid)), }; match match crate::db_get::api_keys::api_key_exists(db, &api_key).await { Ok(exists) => exists, Err(e) => { + // 500 Internal Server Error is sent because of a database error return Outcome::Failure(( - Status::BadRequest, + Status::InternalServerError, AuthError::DataBaseError(e.to_string()), - )) + )); } } { true => Outcome::Success(AuthPreflag(api_key)), diff --git a/src/db_get/api_keys.rs b/src/db_get/api_keys.rs index aca90f1..df536f6 100644 --- a/src/db_get/api_keys.rs +++ b/src/db_get/api_keys.rs @@ -15,6 +15,38 @@ pub async fn api_key_exists(db: &DatabaseConnection, api_key: &str) -> Result Result { + match plotsystem_api_keys::Entity::find() + .join( + JoinType::InnerJoin, + plotsystem_api_keys::Relation::PlotsystemBuildteams.def(), + ) + .join( + JoinType::InnerJoin, + plotsystem_buildteams::Relation::PlotsystemBuildteamHasCountries.def(), + ) + .join( + JoinType::InnerJoin, + plotsystem_buildteam_has_countries::Relation::PlotsystemCountries.def(), + ) + .filter( + Condition::all() + .add(plotsystem_api_keys::Column::ApiKey.eq(api_key.to_owned())) + .add(plotsystem_countries::Column::Id.eq(country_id)), + ) + .all(db) + .await? + .len() + { + 0 => Ok(false), + _ => Ok(true), + } +} + pub async fn cp_related_to_api_key( db: &DatabaseConnection, api_key: &String, diff --git a/src/db_get/builder.rs b/src/db_get/builder.rs new file mode 100644 index 0000000..edd0c56 --- /dev/null +++ b/src/db_get/builder.rs @@ -0,0 +1,18 @@ +use sea_orm::{DatabaseConnection, DbErr}; + +use crate::entities::{prelude::*, *}; +use sea_orm::entity::*; +use uuid::Uuid; + +pub async fn by_uuid( + db: &DatabaseConnection, + uuid: Uuid, +) -> Result, DbErr> { + PlotsystemBuilders::find_by_id(uuid.as_hyphenated().to_string()) + .one(db) + .await +} + +pub async fn all(db: &DatabaseConnection) -> Result, DbErr> { + PlotsystemBuilders::find().all(db).await +} diff --git a/src/db_get/country.rs b/src/db_get/country.rs new file mode 100644 index 0000000..683bc89 --- /dev/null +++ b/src/db_get/country.rs @@ -0,0 +1,22 @@ +use sea_orm::{DatabaseConnection, DbErr}; + +use crate::entities::{prelude::*, *}; + +use sea_orm::entity::*; + +pub async fn by_id( + db: &DatabaseConnection, + id: i32, +) -> Result { + match PlotsystemCountries::find_by_id(id).one(db).await? { + Some(cp) => Ok(cp), + None => Err(DbErr::RecordNotFound(format!( + "Country with id {} does not exists", + id + ))), + } +} + +pub async fn all(db: &DatabaseConnection) -> Result, DbErr> { + PlotsystemCountries::find().all(db).await +} diff --git a/src/db_get/mod.rs b/src/db_get/mod.rs index 1a13210..4997214 100644 --- a/src/db_get/mod.rs +++ b/src/db_get/mod.rs @@ -1,5 +1,7 @@ pub mod api_keys; +pub mod builder; pub mod city_project; +pub mod country; pub mod ftp_configuration; pub mod plot; pub mod server; diff --git a/src/entities/plotsystem_builders.rs b/src/entities/plotsystem_builders.rs index a81b3d2..befe238 100644 --- a/src/entities/plotsystem_builders.rs +++ b/src/entities/plotsystem_builders.rs @@ -11,9 +11,9 @@ pub struct Model { pub name: String, pub score: i32, pub completed_plots: i32, - pub first_slot_id: Option, - pub second_slot_id: Option, - pub third_slot_id: Option, + pub first_slot: Option, + pub second_slot: Option, + pub third_slot: Option, pub lang: Option, } @@ -21,7 +21,7 @@ pub struct Model { pub enum Relation { #[sea_orm( belongs_to = "super::plotsystem_plots::Entity", - from = "Column::FirstSlotId", + from = "Column::FirstSlot", to = "super::plotsystem_plots::Column::Id", on_update = "Restrict", on_delete = "Restrict" @@ -29,7 +29,7 @@ pub enum Relation { PlotsystemPlots3, #[sea_orm( belongs_to = "super::plotsystem_plots::Entity", - from = "Column::SecondSlotId", + from = "Column::SecondSlot", to = "super::plotsystem_plots::Column::Id", on_update = "Restrict", on_delete = "Restrict" @@ -37,7 +37,7 @@ pub enum Relation { PlotsystemPlots2, #[sea_orm( belongs_to = "super::plotsystem_plots::Entity", - from = "Column::ThirdSlotId", + from = "Column::ThirdSlot", to = "super::plotsystem_plots::Column::Id", on_update = "Restrict", on_delete = "Restrict" diff --git a/src/entities/plotsystem_city_projects.rs b/src/entities/plotsystem_city_projects.rs index 09a5c89..795aca4 100644 --- a/src/entities/plotsystem_city_projects.rs +++ b/src/entities/plotsystem_city_projects.rs @@ -11,7 +11,7 @@ pub struct Model { pub country_id: i32, pub name: String, pub description: String, - pub visible: i8, + pub visible: bool, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/entities/plotsystem_ftp_configurations.rs b/src/entities/plotsystem_ftp_configurations.rs index 8ef8c71..d6d0a67 100644 --- a/src/entities/plotsystem_ftp_configurations.rs +++ b/src/entities/plotsystem_ftp_configurations.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; pub struct Model { #[sea_orm(primary_key)] pub id: i32, - pub schematic_path: Option, + pub schematics_path: Option, pub address: String, pub port: i32, #[sea_orm(column_name = "isSFTP")] diff --git a/src/entities/sea_orm_active_enums.rs b/src/entities/sea_orm_active_enums.rs index f727fce..ae71e20 100644 --- a/src/entities/sea_orm_active_enums.rs +++ b/src/entities/sea_orm_active_enums.rs @@ -24,16 +24,16 @@ pub enum Status { )] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "continent")] pub enum Continent { - #[sea_orm(string_value = "Europe")] + #[sea_orm(string_value = "europe")] Europe, - #[sea_orm(string_value = "Asia")] + #[sea_orm(string_value = "asia")] Asia, - #[sea_orm(string_value = "Africa")] + #[sea_orm(string_value = "africa")] Africa, - #[sea_orm(string_value = "Oceania")] + #[sea_orm(string_value = "oceania")] Oceania, - #[sea_orm(string_value = "South America")] + #[sea_orm(string_value = "south america")] SouthAmerica, - #[sea_orm(string_value = "North America")] + #[sea_orm(string_value = "north america")] NorthAmerica, } diff --git a/src/main.rs b/src/main.rs index ecc503d..d1e2db1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,15 +15,28 @@ fn rocket() -> _ { rocket::build().attach(Db::init()).mount( "/api/v1", routes![ - routes::get::ftp_configuration, - routes::get::city_project, - routes::get::city_projects, + routes::cities::city_get_all, + routes::cities::city_get, + routes::cities::city_post, + routes::cities::city_put, + routes::cities::city_delete, + routes::builders::builders_get_all, + routes::builders::builders_get, + routes::countries::country_get_all, + routes::countries::country_get, + routes::ftp::ftp_get, + routes::plots::plot_get, + routes::plots::plots_get, + routes::plots::plot_add, + routes::plots::set_pasted, + // routes::get::ftp_configuration, + // routes::get::city_project, routes::get::server, - routes::get::plot, - routes::get::plots, - routes::get::byte_arr, - routes::post::plot_add, - routes::put::set_pasted, + // routes::get::plot, + // routes::get::plots, + // routes::get::byte_arr, + // routes::post::plot_add, + // routes::put::set_pasted, ], ) } diff --git a/src/routes/builders.rs b/src/routes/builders.rs new file mode 100644 index 0000000..b8e9684 --- /dev/null +++ b/src/routes/builders.rs @@ -0,0 +1,64 @@ +use crate::auth::auth_preflag_request_guard::AuthPreflag; +use crate::{db_get, entities::*, pool::Db}; +use rocket::Request; +use rocket::{http::Status, response, response::Responder, response::Response, serde::json::Json}; +use sea_orm::{ActiveValue::*, EntityTrait}; +use sea_orm_rocket::Connection; +use serde::Deserialize; +use uuid::Uuid; + +pub struct APIResponse(pub Status, pub Option); + +impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for APIResponse { + fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { + let mut build = Response::build(); + if let Some(responder) = self.1 { + build.merge(responder.respond_to(req)?); + } + + build.status(self.0).ok() + } +} + +#[get("/builders")] +pub async fn builders_get_all( + conn: Connection<'_, Db>, +) -> Result>, APIResponse> { + let db = conn.into_inner(); + + match db_get::builder::all(db).await { + Ok(builders) => Ok(Json(builders)), + Err(e) => Err(APIResponse( + Status::InternalServerError, + Some(e.to_string()), + )), + } +} + +#[get("/builder/")] +pub async fn builders_get( + conn: Connection<'_, Db>, + uuid: String, +) -> Result>, APIResponse> { + let db = conn.into_inner(); + + let parsed_uuid = Uuid::parse_str(&uuid); + + if parsed_uuid.is_err() { + return Err(APIResponse(Status::BadRequest, None)); + } + + match db_get::builder::by_uuid(db, parsed_uuid.unwrap()).await { + Ok(builder) => { + if (builder.is_none()) { + Ok(APIResponse(Status::NotFound, None)) + } else { + Ok(APIResponse(Status::Ok, Some(Json(builder.unwrap())))) + } + } + Err(e) => Err(APIResponse( + Status::InternalServerError, + Some(e.to_string()), + )), + } +} diff --git a/src/routes/cities.rs b/src/routes/cities.rs new file mode 100644 index 0000000..ccd127c --- /dev/null +++ b/src/routes/cities.rs @@ -0,0 +1,254 @@ +use crate::auth::auth_preflag_request_guard::AuthPreflag; +use crate::entities::{prelude::*, *}; +use crate::{db_get, entities::*, pool::Db}; +use rocket::Request; +use rocket::{http::Status, response, response::Responder, response::Response, serde::json::Json}; +use sea_orm::{ActiveValue::*, EntityTrait}; +use sea_orm_rocket::Connection; +use serde::Deserialize; + +// get all city projects +// no auth is required for this api request +#[get("/city_projects")] +pub async fn city_get_all( + conn: Connection<'_, Db>, +) -> Result>, Status> { + let db = conn.into_inner(); + + match db_get::city_project::all(db).await { + Ok(cp) => Ok(Json(cp)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} + +// get specific city project +// no auth is required +#[get("/city_project/")] +pub async fn city_get( + conn: Connection<'_, Db>, + id: i32, +) -> Result, Status> { + let db = conn.into_inner(); + + match db_get::city_project::by_cp_id(db, id).await { + Ok(cp) => Ok(Json(cp)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} + +// all fields except ID are required when creating a new city +#[derive(Deserialize)] +pub struct NewCityJson { + pub country_id: i32, + pub name: String, + pub description: String, + pub visible: bool, +} + +// create a new city project +// requires valid api key +// all city fields are required except ID, as it's automatically assigned here +// api key has to be associated with the country for it to save +#[post("/city_project", format = "json", data = "")] +pub async fn city_post( + conn: Connection<'_, Db>, + auth_preflag: AuthPreflag, + city_json: Json, +) -> Result>, APIResponse> { + let db = conn.into_inner(); + + let AuthPreflag(api_key) = auth_preflag; + + match match db_get::api_keys::api_key_exists(db, &api_key).await { + Ok(cp) => cp, + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + } { + true => { + // check if user can use country being specified + match db_get::api_keys::country_related_to_api_key(db, &api_key, city_json.country_id) + .await + { + Ok(country) => { + if !country { + return Err(APIResponse( + Status::Unauthorized, + Some("You don't have access to this country.".to_owned()), + )); + } + } + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + }; + + let city = plotsystem_city_projects::ActiveModel { + id: NotSet, + country_id: Set(city_json.country_id.to_owned()), + name: Set(city_json.name.to_owned()), + description: Set(city_json.description.to_owned()), + visible: Set(city_json.visible.to_owned()), + }; + + // Ok(APIResponse(Status::Ok, None)) + + match plotsystem_city_projects::Entity::insert(city) + .exec(db) + .await + { + Ok(result) => match PlotsystemCityProjects::find_by_id(result.last_insert_id) + .one(db) + .await + { + Ok(city) => Ok(APIResponse(Status::Ok, Some(Json(city.unwrap())))), + Err(e) => Err(APIResponse( + Status::InternalServerError, + Some(e.to_string()), + )), + }, + Err(e) => Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + } + } + false => Ok(APIResponse(Status::Unauthorized, None)), + } +} + +// all modify request values are optional; if one is omitted, don't change it +#[derive(Deserialize)] +pub struct EditCityJson { + pub country_id: Option, + pub name: Option, + pub description: Option, + pub visible: Option, +} + +pub struct APIResponse(pub Status, pub Option); + +impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for APIResponse { + fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { + let mut build = Response::build(); + if let Some(responder) = self.1 { + build.merge(responder.respond_to(req)?); + } + + build.status(self.0).ok() + } +} + +// modifies city project +// requires valid api key that has access to this city project +// api key has to be associated with the country for it to save +#[put("/city_project/", format = "json", data = "")] +pub async fn city_put( + conn: Connection<'_, Db>, + auth_preflag: AuthPreflag, + city_json: Json, + id: i32, +) -> Result> { + let db = conn.into_inner(); + + let AuthPreflag(api_key) = auth_preflag; + + // check if the city being edited can be modified by user + match match db_get::api_keys::cp_related_to_api_key(db, &api_key, id).await { + Ok(cp) => cp, + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), //status::BadRequest(Some(e.to_string())) + } { + true => { + let mut city: plotsystem_city_projects::ActiveModel = + match db_get::city_project::by_cp_id(db, id).await { + Ok(city) => city.into(), + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), //status::BadRequest(Some(e.to_string())) + }; + + // if modifying city project's country; check if user has access to said country + if !city_json.country_id.is_none() { + match db_get::api_keys::country_related_to_api_key( + db, + &api_key, + city_json.country_id.unwrap(), + ) + .await + { + Ok(country) => { + if !country { + return Err(APIResponse( + Status::Unauthorized, + Some("You don't have access to this country.".to_owned()), + )); + } + } + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + }; + } + + let mut modified = false; + + if !city_json.country_id.is_none() { + city.country_id = Set(city_json.country_id.unwrap().to_owned()); + modified = true; + } + + if !city_json.name.is_none() { + city.name = Set(city_json.name.as_ref().unwrap().to_owned()); + modified = true; + } + + if !city_json.description.is_none() { + city.description = Set(city_json.description.as_ref().unwrap().to_owned()); + modified = true; + } + + if !city_json.visible.is_none() { + city.visible = Set(city_json.visible.unwrap().to_owned()); + modified = true; + } + + if !modified { + return Err(APIResponse(Status::NotModified, None)); + } + + match plotsystem_city_projects::Entity::update(city) + .exec(db) + .await + { + Ok(_) => Ok(Status::Ok), + Err(e) => Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + } + } + false => Ok(Status::Unauthorized), + } +} + +// deletes a city project +// api key has to be associated with this city project to delete it +#[delete("/city_project/")] +pub async fn city_delete( + conn: Connection<'_, Db>, + auth_preflag: AuthPreflag, + id: i32, +) -> Result> { + let db = conn.into_inner(); + let AuthPreflag(api_key) = auth_preflag; + + match match db_get::api_keys::cp_related_to_api_key(db, &api_key, id).await { + Ok(cp) => cp, + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + } { + true => { + let city: plotsystem_city_projects::ActiveModel = + match db_get::city_project::by_cp_id(db, id).await { + Ok(city) => city.into(), + Err(e) => return Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + }; + + match plotsystem_city_projects::Entity::delete(city) + .exec(db) + .await + { + Ok(_) => Ok(Status::Ok), + Err(e) => Err(APIResponse(Status::BadRequest, Some(e.to_string()))), + } + } + false => Ok(Status::Unauthorized), + } +} diff --git a/src/routes/countries.rs b/src/routes/countries.rs new file mode 100644 index 0000000..3eafb5e --- /dev/null +++ b/src/routes/countries.rs @@ -0,0 +1,37 @@ +use crate::auth::auth_preflag_request_guard::AuthPreflag; +use crate::entities::{prelude::*, *}; +use crate::{db_get, entities::*, pool::Db}; +use rocket::Request; +use rocket::{http::Status, response, response::Responder, response::Response, serde::json::Json}; +use sea_orm::{ActiveValue::*, EntityTrait}; +use sea_orm_rocket::Connection; +use serde::Deserialize; + +// get all countries +// no auth is required for this api request +#[get("/countries")] +pub async fn country_get_all( + conn: Connection<'_, Db>, +) -> Result>, Status> { + let db = conn.into_inner(); + + match db_get::country::all(db).await { + Ok(cp) => Ok(Json(cp)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} + +#[get("/country/")] +pub async fn country_get( + conn: Connection<'_, Db>, + id: i32, +) -> Result, Status> { + let db = conn.into_inner(); + + match db_get::country::by_id(db, id).await { + Ok(cp) => Ok(Json(cp)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} diff --git a/src/routes/ftp.rs b/src/routes/ftp.rs new file mode 100644 index 0000000..dda30bd --- /dev/null +++ b/src/routes/ftp.rs @@ -0,0 +1,22 @@ +use crate::auth::auth_preflag_request_guard::AuthPreflag; +use crate::entities::{prelude::*, *}; +use crate::{db_get, entities::*, pool::Db}; +use rocket::Request; +use rocket::{http::Status, response, response::Responder, response::Response, serde::json::Json}; +use sea_orm::{ActiveValue::*, EntityTrait}; +use sea_orm_rocket::Connection; +use serde::Deserialize; + +#[get("/ftp/")] +pub async fn ftp_get( + conn: Connection<'_, Db>, + id: i32, +) -> Result, Status> { + let db = conn.into_inner(); + + match db_get::ftp_configuration::by_ftp_id(db, id).await { + Ok(cp) => Ok(Json(cp)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} diff --git a/src/routes/get.rs b/src/routes/get.rs index 6ebaa60..6264ea6 100644 --- a/src/routes/get.rs +++ b/src/routes/get.rs @@ -3,56 +3,6 @@ use crate::{db_get, entities::*, pool::Db}; use rocket::{http::Status, serde::json::Json}; use sea_orm_rocket::Connection; -#[get("/ftp_configuration//")] -pub async fn ftp_configuration( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, - _auth: FtpAuth, - id_type: String, - id: i32, -) -> Result, Status> { - let db = conn.into_inner(); - - match match id_type.as_str() { - "ftp_id" => db_get::ftp_configuration::by_ftp_id(db, id).await, - "server_id" => db_get::ftp_configuration::by_server_id(db, id).await, - "cp_id" => db_get::ftp_configuration::by_cp_id(db, id).await, - _ => return Err(Status::BadRequest), - } { - Ok(ftp_configuration) => Ok(Json(ftp_configuration)), - Err(_) => Err(Status::BadRequest), - } -} - -#[get("/city_project/")] -pub async fn city_project( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, - id: i32, -) -> Result, Status> { - let db = conn.into_inner(); - - match db_get::city_project::by_cp_id(db, id).await { - Ok(cp) => Ok(Json(cp)), - // Return error message in status - Err(_) => Err(Status::BadRequest), - } -} - -#[get("/city_projects")] -pub async fn city_projects( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, -) -> Result>, Status> { - let db = conn.into_inner(); - - match db_get::city_project::all(db).await { - Ok(cp) => Ok(Json(cp)), - // Return error message in status - Err(_) => Err(Status::BadRequest), - } -} - #[get("/server//")] pub async fn server( conn: Connection<'_, Db>, @@ -71,43 +21,3 @@ pub async fn server( Err(_) => Err(Status::BadRequest), } } - -#[get("/plot/")] -pub async fn plot( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, - plot_id: i32, -) -> Result, Status> { - let db = conn.into_inner(); - - match db_get::plot::by_plot_id(db, plot_id).await { - Ok(plot) => Ok(Json(plot)), - // Return error message in status - Err(_) => Err(Status::BadRequest), - } -} - -#[get("/plots?&&")] -pub async fn plots( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, - status: Option, - pasted: Option, - limit: Option, -) -> Result>, Status> { - let db = conn.into_inner(); - - match db_get::plot::filtered(db, status, pasted, limit).await { - Ok(plots) => Ok(Json(plots)), - // Return error message in status - Err(_) => Err(Status::BadRequest), - } -} - -#[get("/")] -pub async fn byte_arr(bytes: String) -> Status { - return match bytes.as_bytes() == [112_u8, 105_u8, 112_u8, 112_u8, 101_u8, 110_u8] { - true => Status::ExpectationFailed, - false => Status::NotFound, - }; -} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index fce30c3..cb66c56 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,3 +1,6 @@ +pub mod builders; +pub mod cities; +pub mod countries; +pub mod ftp; pub mod get; -pub mod post; -pub mod put; +pub mod plots; diff --git a/src/routes/post.rs b/src/routes/plots.rs similarity index 53% rename from src/routes/post.rs rename to src/routes/plots.rs index f93363b..522927a 100644 --- a/src/routes/post.rs +++ b/src/routes/plots.rs @@ -1,11 +1,48 @@ -use crate::auth::auth_preflag_request_guard::AuthPreflag; +use crate::auth::{ + auth_preflag_request_guard::AuthPreflag, auth_put_plot_request_guard::AuthPutGuard, +}; +use crate::entities::{prelude::*, *}; use crate::{db_get, entities::*, pool::Db}; - -use rocket::{http::Status, response::status, serde::json::Json}; +use rocket::Request; +use rocket::{ + http::Status, response::status, response::Responder, response::Response, serde::json::Json, +}; use sea_orm::{ActiveValue::*, EntityTrait}; use sea_orm_rocket::Connection; use serde::Deserialize; +#[get("/plot/")] +pub async fn plot_get( + conn: Connection<'_, Db>, + _auth_preflag: AuthPreflag, + plot_id: i32, +) -> Result, Status> { + let db = conn.into_inner(); + + match db_get::plot::by_plot_id(db, plot_id).await { + Ok(plot) => Ok(Json(plot)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} + +#[get("/plots?&&")] +pub async fn plots_get( + conn: Connection<'_, Db>, + _auth_preflag: AuthPreflag, + status: Option, + pasted: Option, + limit: Option, +) -> Result>, Status> { + let db = conn.into_inner(); + + match db_get::plot::filtered(db, status, pasted, limit).await { + Ok(plots) => Ok(Json(plots)), + // Return error message in status + Err(_) => Err(Status::BadRequest), + } +} + #[derive(Deserialize)] pub struct PlotRequestJson { pub city_project_id: i32, @@ -15,7 +52,7 @@ pub struct PlotRequestJson { pub outline: String, } -#[post("/plot/add", format = "json", data = "")] +#[post("/plot", format = "json", data = "")] pub async fn plot_add( conn: Connection<'_, Db>, auth_preflag: AuthPreflag, @@ -61,3 +98,27 @@ pub async fn plot_add( false => Ok(Status::Unauthorized), } } + +#[put("/plot/set_pasted/?")] +pub async fn set_pasted( + conn: Connection<'_, Db>, + _auth_preflag: AuthPreflag, + _auth: AuthPutGuard, + plot_id: i32, + pasted: i8, +) -> Status { + let db = conn.into_inner(); + + let mut plot: plotsystem_plots::ActiveModel = match db_get::plot::by_plot_id(db, plot_id).await + { + Ok(plot) => plot.into(), + Err(_) => return Status::BadRequest, + }; + + plot.pasted = Set(pasted); + + return match plotsystem_plots::Entity::update(plot).exec(db).await { + Ok(_) => Status::Ok, + Err(_) => Status::InternalServerError, + }; +} diff --git a/src/routes/put.rs b/src/routes/put.rs deleted file mode 100644 index b44a9c8..0000000 --- a/src/routes/put.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::auth::{ - auth_preflag_request_guard::AuthPreflag, auth_put_plot_request_guard::AuthPutGuard, -}; -use crate::{db_get, entities::*, pool::Db}; -use rocket::http::Status; -use sea_orm::{ActiveModelTrait, ActiveValue::*}; -use sea_orm_rocket::Connection; - -#[put("/plot/set_pasted/?")] -pub async fn set_pasted( - conn: Connection<'_, Db>, - _auth_preflag: AuthPreflag, - _auth: AuthPutGuard, - plot_id: i32, - pasted: i8, -) -> Status { - let db = conn.into_inner(); - - let mut plot: plotsystem_plots::ActiveModel = match db_get::plot::by_plot_id(db, plot_id).await - { - Ok(plot) => plot.into(), - Err(_) => return Status::BadRequest, - }; - - plot.pasted = Set(pasted); - - return match plot.update(db).await { - Ok(_) => Status::Ok, - Err(_) => Status::InternalServerError, - }; -}