From 28303cb48f71b63b58c2eed879ab3e6aa0b398dc Mon Sep 17 00:00:00 2001 From: Franklin Date: Wed, 26 Apr 2023 09:59:54 -0400 Subject: [PATCH] Added deploy --- Cargo.toml | 1 - deploy/Dockerfile | 4 ++++ deploy/deploy-to-backend.sh | 6 +++++ src/dao/agent.rs | 2 +- src/main.rs | 2 +- src/routes/admin.rs | 48 +++++++++++++++++++++++++++++++++---- src/routes/main_router.rs | 3 ++- src/utils/auth.rs | 23 ++++++++++++++++++ src/utils/macros.rs | 17 +++++++++++++ src/utils/mod.rs | 1 + 10 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 deploy/Dockerfile create mode 100755 deploy/deploy-to-backend.sh create mode 100644 src/utils/auth.rs diff --git a/Cargo.toml b/Cargo.toml index 7e96ccc..e605197 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ actix-cors = "0.6.2" actix-multipart = "0.6.0" uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics"] } - actix-web-utils = { git = "https://git.franklinblanco.dev/franklinblanco/actix-web-utils.git" } err = { git = "https://git.franklinblanco.dev/franklinblanco/err.git" } diff --git a/deploy/Dockerfile b/deploy/Dockerfile new file mode 100644 index 0000000..14923ce --- /dev/null +++ b/deploy/Dockerfile @@ -0,0 +1,4 @@ +FROM --platform=linux/amd64 ubuntu +COPY jl-backend / +EXPOSE 8080 +CMD ["./jl-backend"] \ No newline at end of file diff --git a/deploy/deploy-to-backend.sh b/deploy/deploy-to-backend.sh new file mode 100755 index 0000000..2a05027 --- /dev/null +++ b/deploy/deploy-to-backend.sh @@ -0,0 +1,6 @@ +export CC_x86_64_unknown_linux_gnu=x86_64-unknown-linux-gnu-gcc +export CXX_x86_64_unknown_linux_gnu=x86_64-unknown-linux-gnu-g++ +export AR_x86_64_unknown_linux_gnu=x86_64-unknown-linux-gnu-ar +export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-unknown-linux-gnu-gcc +cargo build --release --target x86_64-unknown-linux-gnu +scp -i ~/Developer/kp/main-key-pair.pem $CARGO_TARGET_DIR/x86_64-unknown-linux-gnu/release/jl-backend deploy/Dockerfile ubuntu@18.118.145.141:~/executables/jl-backend/ \ No newline at end of file diff --git a/src/dao/agent.rs b/src/dao/agent.rs index b6da266..92e82e9 100644 --- a/src/dao/agent.rs +++ b/src/dao/agent.rs @@ -55,8 +55,8 @@ pub async fn update_agent( sqlx::query_file_as!( Agent, "sql/agent/update.sql", - agent.shortcode, agent.full_name, + agent.shortcode, agent.credential, agent.credential_type as _, agent.profile_picture_url, diff --git a/src/main.rs b/src/main.rs index 98374fe..e5b0743 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ async fn main() { let start_time = Utc::now().timestamp_millis(); let db_conn = Arc::new(main_dao::connect_to_database().await.unwrap()); - + // Pass shared state to server and start it routes::main_router::start_all_routes(start_time, db_conn) .await diff --git a/src/routes/admin.rs b/src/routes/admin.rs index 72baf52..199ffda 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -6,6 +6,7 @@ use actix_web::{ web::{self, Path}, }; use actix_web_utils::extensions::typed_response::TypedHttpResponse; +use err::MessageResource; use jl_types::{ domain::{ agent::Agent, contact::Contact, count::Count, location::Location, project::Project, @@ -18,19 +19,21 @@ use jl_types::{ location::NewLocationPayload, project::{NewProjectPayload, UpdateProjectPayload}, unit::{NewUnitPayload, UpdateUnitPayload}, - }, + }, auth::AuthDto, }, }; use sqlx::PgPool; use uuid::Uuid; -use crate::services; +use crate::{services, auth, utils::auth::generate_token, success}; #[post("/agent")] pub async fn create_new_agent_profile( db_conn: web::Data>, new_agent_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::create_new_agent_profile(&db_conn, new_agent_payload.0).await } @@ -38,7 +41,9 @@ pub async fn create_new_agent_profile( pub async fn create_new_location( db_conn: web::Data>, new_location_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::create_new_location(&db_conn, new_location_payload.0).await } @@ -46,7 +51,9 @@ pub async fn create_new_location( pub async fn create_new_project( db_conn: web::Data>, new_project_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::create_new_project(&db_conn, new_project_payload.0).await } @@ -54,7 +61,9 @@ pub async fn create_new_project( pub async fn create_new_unit( db_conn: web::Data>, new_unit_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::create_new_unit(&db_conn, new_unit_payload.0).await } @@ -62,7 +71,9 @@ pub async fn create_new_unit( pub async fn update_agent( db_conn: web::Data>, update_agent_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::update_agent(&db_conn, update_agent_payload.0).await } @@ -70,7 +81,9 @@ pub async fn update_agent( pub async fn update_project( db_conn: web::Data>, update_project_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::update_project(&db_conn, update_project_payload.0).await } @@ -78,7 +91,9 @@ pub async fn update_project( pub async fn update_unit( db_conn: web::Data>, update_unit_payload: web::Json, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::update_unit(&db_conn, update_unit_payload.0).await } @@ -86,7 +101,9 @@ pub async fn update_unit( pub async fn delete_agent( db_conn: web::Data>, agent_id: Path, + request: actix_web::HttpRequest, ) -> TypedHttpResponse<()> { + auth!(request); services::admin::delete_agent(&db_conn, &agent_id).await } @@ -94,7 +111,9 @@ pub async fn delete_agent( pub async fn delete_location( db_conn: web::Data>, location_id: Path, + request: actix_web::HttpRequest, ) -> TypedHttpResponse<()> { + auth!(request); services::admin::delete_location(&db_conn, &location_id).await } @@ -102,7 +121,9 @@ pub async fn delete_location( pub async fn delete_project( db_conn: web::Data>, project_id: Path, + request: actix_web::HttpRequest, ) -> TypedHttpResponse<()> { + auth!(request); services::admin::delete_project(&db_conn, &project_id).await } @@ -110,22 +131,27 @@ pub async fn delete_project( pub async fn delete_unit( db_conn: web::Data>, unit_id: Path, + request: actix_web::HttpRequest, ) -> TypedHttpResponse<()> { + auth!(request); services::admin::delete_unit(&db_conn, &unit_id).await } #[get("visits/count")] -pub async fn get_visits_count(db_conn: web::Data>) -> TypedHttpResponse { +pub async fn get_visits_count(db_conn: web::Data>, request: actix_web::HttpRequest,) -> TypedHttpResponse { + auth!(request); services::admin::get_all_page_visits(&db_conn).await } #[get("contacts/count")] -pub async fn get_contacts_count(db_conn: web::Data>) -> TypedHttpResponse { +pub async fn get_contacts_count(db_conn: web::Data>, request: actix_web::HttpRequest,) -> TypedHttpResponse { + auth!(request); services::admin::get_contact_count(&db_conn).await } #[get("contacts")] -pub async fn get_all_contacts(db_conn: web::Data>) -> TypedHttpResponse> { +pub async fn get_all_contacts(db_conn: web::Data>, request: actix_web::HttpRequest,) -> TypedHttpResponse> { + auth!(request); services::admin::get_all_contacts(&db_conn).await } @@ -134,6 +160,18 @@ pub async fn upload_image( aws_client: web::Data>, path_vars: Path, multipart: Multipart, + request: actix_web::HttpRequest, ) -> TypedHttpResponse { + auth!(request); services::admin::upload_image(&aws_client, path_vars.clone(), multipart).await } + +#[post("auth")] +pub async fn authenticate( + authentication_dto: web::Json, +) -> TypedHttpResponse { + match generate_token(&authentication_dto.0.email, &authentication_dto.0.password) { + Ok(token) => success!(token), + Err(_) => TypedHttpResponse::return_standard_error(401, MessageResource::new_from_str("Wrong credentials.")) + } +} \ No newline at end of file diff --git a/src/routes/main_router.rs b/src/routes/main_router.rs index f18a4d4..c350df4 100644 --- a/src/routes/main_router.rs +++ b/src/routes/main_router.rs @@ -41,7 +41,8 @@ pub async fn start_all_routes(start_time: i64, db_conn: Arc) -> Result<( .service(super::admin::get_all_contacts) .service(super::admin::get_contacts_count) .service(super::admin::get_visits_count) - .service(super::admin::upload_image), + .service(super::admin::upload_image) + .service(super::admin::authenticate), ) .service( web::scope("/read") diff --git a/src/utils/auth.rs b/src/utils/auth.rs new file mode 100644 index 0000000..4c4fddd --- /dev/null +++ b/src/utils/auth.rs @@ -0,0 +1,23 @@ +use std::sync::{RwLock}; + +use rand::{distributions::Alphanumeric, Rng}; + +pub static AUTH_TOKEN: RwLock> = RwLock::new(None); + +pub fn generate_token(email: &String, password: &String) -> Result { + let actual_email = env!("JL_EMAIL"); + let actual_password = env!("JL_PASSWORD"); + if email == &actual_email && password == &actual_password { + let token: String = rand::thread_rng().sample_iter(&Alphanumeric).take(255).map(char::from).collect(); + let mut lock = AUTH_TOKEN.write().expect("ERROR LOCKING RWLOCK"); + *lock = Some(token.clone()); + Ok(token) + } else { + Err(()) + } +} + +pub fn get_token() -> Option { + let lock = AUTH_TOKEN.read().expect("ERROR LOCKING RWLOCK"); + lock.clone() +} \ No newline at end of file diff --git a/src/utils/macros.rs b/src/utils/macros.rs index ea467b3..ee0443b 100644 --- a/src/utils/macros.rs +++ b/src/utils/macros.rs @@ -55,3 +55,20 @@ macro_rules! unwrap_or_not_found { } }; } + +/// This macro does the authentication needed for all the admin routes. give it a user and password as params. +#[macro_export] +macro_rules! auth { + ($request:expr) => { + let __auth_token_header = match $request.headers().get("auth_token") { + Some(header_val) => {header_val.to_str().expect("ASCII Chars")}, + None => {return actix_web_utils::extensions::typed_response::TypedHttpResponse::return_standard_error(401, err::MessageResource::new_from_string(format!("No Token in header.")))} + }; + match crate::utils::auth::get_token() { + Some(token) => if token == __auth_token_header {} else { + return actix_web_utils::extensions::typed_response::TypedHttpResponse::return_standard_error(401, err::MessageResource::new_from_string(format!("Incorrect Token."))) + }, + None => return actix_web_utils::extensions::typed_response::TypedHttpResponse::return_standard_error(401, err::MessageResource::new_from_string(format!("No Token in backend. Please authenticate."))), + } + }; +} \ No newline at end of file diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8e69244..d5030d4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ pub mod macros; pub mod s3; pub mod visit; +pub mod auth; \ No newline at end of file