From d65b92e3be336b696810a724a7709858e6af0ac7 Mon Sep 17 00:00:00 2001 From: EETagent Date: Mon, 7 Nov 2022 13:28:50 +0100 Subject: [PATCH] feat: move routes inside route dir, require admin auth for candidate create operation --- api/src/lib.rs | 99 +++++++++---------------------------- api/src/routes/admin.rs | 76 ++++++++++++++++++++++++++++ api/src/routes/candidate.rs | 63 +++++++++++++++++++++++ api/src/routes/mod.rs | 2 + 4 files changed, 163 insertions(+), 77 deletions(-) create mode 100644 api/src/routes/admin.rs create mode 100644 api/src/routes/candidate.rs diff --git a/api/src/lib.rs b/api/src/lib.rs index 480e8f9..cd1550d 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -1,23 +1,15 @@ #[macro_use] extern crate rocket; -use std::net::SocketAddr; - -use guards::request::auth::{CandidateAuth, AdminAuth}; -use portfolio_core::services::candidate_service::{CandidateService, UserDetails}; -use requests::{LoginRequest, RegisterRequest}; -use rocket::http::Status; -use rocket::{Rocket, Build}; -use rocket::serde::json::Json; use rocket::fairing::{self, AdHoc}; -use rocket::response::status::Custom; -use migration::{MigratorTrait}; -use sea_orm_rocket::{Connection, Database}; +use rocket::{Build, Rocket}; +use migration::MigratorTrait; +use sea_orm_rocket::Database; -mod pool; mod guards; +mod pool; mod requests; mod routes; @@ -26,70 +18,6 @@ use pool::Db; pub use entity::candidate; pub use entity::candidate::Entity as Candidate; -use portfolio_core::crypto::random_8_char_string; - -#[post("/", data = "")] -async fn create(conn: Connection<'_, Db>, post_form: Json) -> Result> { - let db = conn.into_inner(); - let form = post_form.into_inner(); - - let plain_text_password = random_8_char_string(); - - let candidate = CandidateService::create(db, form.application_id, &plain_text_password, form.personal_id_number) - .await; - - if candidate.is_err() { // TODO cleanup - let e = candidate.err().unwrap(); - return Err(Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())); - } - - Ok(plain_text_password) -} - -#[get("/whoami")] -async fn validate(session: CandidateAuth) -> Result> { - let candidate: entity::candidate::Model = session.into(); - Ok(candidate.application.to_string()) -} - -#[get("/admin")] -async fn admin(session: AdminAuth) -> Result> { - Ok("Hello admin".to_string()) -} - -#[put("/details", data = "
")] -async fn fill_details(conn: Connection<'_, Db>, details: Json, session: CandidateAuth) -> Result> { - let db = conn.into_inner(); - let form = details.into_inner(); - let candidate: entity::candidate::Model = session.into(); - - let candidate = CandidateService::add_user_details(db, candidate, form) - .await; - - if candidate.is_err() { // TODO cleanup - let e = candidate.err().unwrap(); - return Err(Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())); - } - - Ok("Details added".to_string()) -} - -#[post("/login", data = "")] -async fn login(conn: Connection<'_, Db>, login_form: Json, ip_addr: SocketAddr) -> Result> { - let db = conn.into_inner(); - println!("{} {}", login_form.application_id, login_form.password); - - let session_token = CandidateService::login( - db, - login_form.application_id, - login_form.password.to_string(), - ip_addr.ip().to_string() - ) - .await; - - session_token.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())) -} - #[get("/hello")] async fn hello() -> &'static str { "Hello, world!" @@ -107,7 +35,24 @@ async fn start() -> Result<(), rocket::Error> { .attach(Db::init()) .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) //.mount("/", FileServer::from(relative!("/static"))) - .mount("/", routes![create, login, hello, validate, fill_details, admin]) + .mount("/", routes![hello]) + .mount( + "/candidate/", + routes![ + routes::candidate::login, + routes::candidate::whoami, + routes::candidate::fill_details, + ], + ) + .mount( + "/admin/", + routes![ + routes::admin::login, + routes::admin::whoami, + routes::admin::hello, + routes::admin::create_candidate, + ], + ) .register("/", catchers![]) .launch() .await diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs new file mode 100644 index 0000000..eeb3bd7 --- /dev/null +++ b/api/src/routes/admin.rs @@ -0,0 +1,76 @@ +use std::net::SocketAddr; + +use portfolio_core::{ + crypto::random_8_char_string, + services::{admin_service::AdminService, candidate_service::CandidateService}, +}; +use requests::{AdminLoginRequest, RegisterRequest}; +use rocket::http::Status; +use rocket::response::status::Custom; +use rocket::serde::json::Json; + +use sea_orm_rocket::Connection; + +use crate::{guards::request::auth::AdminAuth, pool::Db, requests}; + +#[post("/login", data = "")] +pub async fn login( + conn: Connection<'_, Db>, + login_form: Json, + ip_addr: SocketAddr, +) -> Result> { + let db = conn.into_inner(); + println!("{} {}", login_form.admin_id, login_form.password); + + let session_token = AdminService::login( + db, + login_form.admin_id, + login_form.password.to_string(), + ip_addr.ip().to_string(), + ) + .await; + + session_token.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())) +} + +#[get("/whoami")] +pub async fn whoami(session: AdminAuth) -> Result> { + let admin: entity::admin::Model = session.into(); + Ok(admin.id.to_string()) +} + +#[get("/hello")] +pub async fn hello(_session: AdminAuth) -> Result> { + Ok("Hello admin".to_string()) +} + +#[post("/create", data = "")] +pub async fn create_candidate( + conn: Connection<'_, Db>, + _session: AdminAuth, + post_form: Json, +) -> Result> { + let db = conn.into_inner(); + let form = post_form.into_inner(); + + let plain_text_password = random_8_char_string(); + + let candidate = CandidateService::create( + db, + form.application_id, + &plain_text_password, + form.personal_id_number, + ) + .await; + + if candidate.is_err() { + // TODO cleanup + let e = candidate.err().unwrap(); + return Err(Custom( + Status::from_code(e.code()).unwrap_or_default(), + e.message(), + )); + } + + Ok(plain_text_password) +} diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs new file mode 100644 index 0000000..2ff7623 --- /dev/null +++ b/api/src/routes/candidate.rs @@ -0,0 +1,63 @@ +use std::net::SocketAddr; + +use portfolio_core::services::candidate_service::{CandidateService, UserDetails}; +use requests::LoginRequest; +use rocket::http::Status; +use rocket::response::status::Custom; +use rocket::serde::json::Json; + +use sea_orm_rocket::Connection; + +use crate::{guards::request::auth::CandidateAuth, pool::Db, requests}; + +#[post("/login", data = "")] +pub async fn login( + conn: Connection<'_, Db>, + login_form: Json, + ip_addr: SocketAddr, +) -> Result> { + let db = conn.into_inner(); + println!("{} {}", login_form.application_id, login_form.password); + + let session_token = CandidateService::login( + db, + login_form.application_id, + login_form.password.to_string(), + ip_addr.ip().to_string(), + ) + .await; + + session_token.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())) +} + + +#[get("/whoami")] +pub async fn whoami(session: CandidateAuth) -> Result> { + let candidate: entity::candidate::Model = session.into(); + Ok(candidate.application.to_string()) +} + +#[put("/details", data = "
")] +pub async fn fill_details( + conn: Connection<'_, Db>, + details: Json, + session: CandidateAuth, +) -> Result> { + let db = conn.into_inner(); + let form = details.into_inner(); + let candidate: entity::candidate::Model = session.into(); + + let candidate = CandidateService::add_user_details(db, candidate, form).await; + + if candidate.is_err() { + // TODO cleanup + let e = candidate.err().unwrap(); + return Err(Custom( + Status::from_code(e.code()).unwrap_or_default(), + e.message(), + )); + } + + Ok("Details added".to_string()) +} + diff --git a/api/src/routes/mod.rs b/api/src/routes/mod.rs index e69de29..90ca91f 100644 --- a/api/src/routes/mod.rs +++ b/api/src/routes/mod.rs @@ -0,0 +1,2 @@ +pub mod admin; +pub mod candidate; \ No newline at end of file