Added deploy

This commit is contained in:
Franklin 2023-04-26 09:59:54 -04:00
parent 4b0f963579
commit 28303cb48f
10 changed files with 98 additions and 9 deletions

View File

@ -22,7 +22,6 @@ actix-cors = "0.6.2"
actix-multipart = "0.6.0" actix-multipart = "0.6.0"
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics"] } uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics"] }
actix-web-utils = { git = "https://git.franklinblanco.dev/franklinblanco/actix-web-utils.git" } actix-web-utils = { git = "https://git.franklinblanco.dev/franklinblanco/actix-web-utils.git" }
err = { git = "https://git.franklinblanco.dev/franklinblanco/err.git" } err = { git = "https://git.franklinblanco.dev/franklinblanco/err.git" }

4
deploy/Dockerfile Normal file
View File

@ -0,0 +1,4 @@
FROM --platform=linux/amd64 ubuntu
COPY jl-backend /
EXPOSE 8080
CMD ["./jl-backend"]

6
deploy/deploy-to-backend.sh Executable file
View File

@ -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/

View File

@ -55,8 +55,8 @@ pub async fn update_agent(
sqlx::query_file_as!( sqlx::query_file_as!(
Agent, Agent,
"sql/agent/update.sql", "sql/agent/update.sql",
agent.shortcode,
agent.full_name, agent.full_name,
agent.shortcode,
agent.credential, agent.credential,
agent.credential_type as _, agent.credential_type as _,
agent.profile_picture_url, agent.profile_picture_url,

View File

@ -13,7 +13,7 @@ async fn main() {
let start_time = Utc::now().timestamp_millis(); let start_time = Utc::now().timestamp_millis();
let db_conn = Arc::new(main_dao::connect_to_database().await.unwrap()); let db_conn = Arc::new(main_dao::connect_to_database().await.unwrap());
// Pass shared state to server and start it // Pass shared state to server and start it
routes::main_router::start_all_routes(start_time, db_conn) routes::main_router::start_all_routes(start_time, db_conn)
.await .await

View File

@ -6,6 +6,7 @@ use actix_web::{
web::{self, Path}, web::{self, Path},
}; };
use actix_web_utils::extensions::typed_response::TypedHttpResponse; use actix_web_utils::extensions::typed_response::TypedHttpResponse;
use err::MessageResource;
use jl_types::{ use jl_types::{
domain::{ domain::{
agent::Agent, contact::Contact, count::Count, location::Location, project::Project, agent::Agent, contact::Contact, count::Count, location::Location, project::Project,
@ -18,19 +19,21 @@ use jl_types::{
location::NewLocationPayload, location::NewLocationPayload,
project::{NewProjectPayload, UpdateProjectPayload}, project::{NewProjectPayload, UpdateProjectPayload},
unit::{NewUnitPayload, UpdateUnitPayload}, unit::{NewUnitPayload, UpdateUnitPayload},
}, }, auth::AuthDto,
}, },
}; };
use sqlx::PgPool; use sqlx::PgPool;
use uuid::Uuid; use uuid::Uuid;
use crate::services; use crate::{services, auth, utils::auth::generate_token, success};
#[post("/agent")] #[post("/agent")]
pub async fn create_new_agent_profile( pub async fn create_new_agent_profile(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
new_agent_payload: web::Json<NewAgentPayload>, new_agent_payload: web::Json<NewAgentPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Agent> { ) -> TypedHttpResponse<Agent> {
auth!(request);
services::admin::create_new_agent_profile(&db_conn, new_agent_payload.0).await 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( pub async fn create_new_location(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
new_location_payload: web::Json<NewLocationPayload>, new_location_payload: web::Json<NewLocationPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Location> { ) -> TypedHttpResponse<Location> {
auth!(request);
services::admin::create_new_location(&db_conn, new_location_payload.0).await 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( pub async fn create_new_project(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
new_project_payload: web::Json<NewProjectPayload>, new_project_payload: web::Json<NewProjectPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Project> { ) -> TypedHttpResponse<Project> {
auth!(request);
services::admin::create_new_project(&db_conn, new_project_payload.0).await 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( pub async fn create_new_unit(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
new_unit_payload: web::Json<NewUnitPayload>, new_unit_payload: web::Json<NewUnitPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Unit> { ) -> TypedHttpResponse<Unit> {
auth!(request);
services::admin::create_new_unit(&db_conn, new_unit_payload.0).await 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( pub async fn update_agent(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
update_agent_payload: web::Json<UpdateAgentPayload>, update_agent_payload: web::Json<UpdateAgentPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Agent> { ) -> TypedHttpResponse<Agent> {
auth!(request);
services::admin::update_agent(&db_conn, update_agent_payload.0).await 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( pub async fn update_project(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
update_project_payload: web::Json<UpdateProjectPayload>, update_project_payload: web::Json<UpdateProjectPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Project> { ) -> TypedHttpResponse<Project> {
auth!(request);
services::admin::update_project(&db_conn, update_project_payload.0).await 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( pub async fn update_unit(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
update_unit_payload: web::Json<UpdateUnitPayload>, update_unit_payload: web::Json<UpdateUnitPayload>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<Unit> { ) -> TypedHttpResponse<Unit> {
auth!(request);
services::admin::update_unit(&db_conn, update_unit_payload.0).await 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( pub async fn delete_agent(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
agent_id: Path<Uuid>, agent_id: Path<Uuid>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<()> { ) -> TypedHttpResponse<()> {
auth!(request);
services::admin::delete_agent(&db_conn, &agent_id).await services::admin::delete_agent(&db_conn, &agent_id).await
} }
@ -94,7 +111,9 @@ pub async fn delete_agent(
pub async fn delete_location( pub async fn delete_location(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
location_id: Path<Uuid>, location_id: Path<Uuid>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<()> { ) -> TypedHttpResponse<()> {
auth!(request);
services::admin::delete_location(&db_conn, &location_id).await services::admin::delete_location(&db_conn, &location_id).await
} }
@ -102,7 +121,9 @@ pub async fn delete_location(
pub async fn delete_project( pub async fn delete_project(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
project_id: Path<Uuid>, project_id: Path<Uuid>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<()> { ) -> TypedHttpResponse<()> {
auth!(request);
services::admin::delete_project(&db_conn, &project_id).await services::admin::delete_project(&db_conn, &project_id).await
} }
@ -110,22 +131,27 @@ pub async fn delete_project(
pub async fn delete_unit( pub async fn delete_unit(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
unit_id: Path<Uuid>, unit_id: Path<Uuid>,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<()> { ) -> TypedHttpResponse<()> {
auth!(request);
services::admin::delete_unit(&db_conn, &unit_id).await services::admin::delete_unit(&db_conn, &unit_id).await
} }
#[get("visits/count")] #[get("visits/count")]
pub async fn get_visits_count(db_conn: web::Data<Arc<PgPool>>) -> TypedHttpResponse<Count> { pub async fn get_visits_count(db_conn: web::Data<Arc<PgPool>>, request: actix_web::HttpRequest,) -> TypedHttpResponse<Count> {
auth!(request);
services::admin::get_all_page_visits(&db_conn).await services::admin::get_all_page_visits(&db_conn).await
} }
#[get("contacts/count")] #[get("contacts/count")]
pub async fn get_contacts_count(db_conn: web::Data<Arc<PgPool>>) -> TypedHttpResponse<Count> { pub async fn get_contacts_count(db_conn: web::Data<Arc<PgPool>>, request: actix_web::HttpRequest,) -> TypedHttpResponse<Count> {
auth!(request);
services::admin::get_contact_count(&db_conn).await services::admin::get_contact_count(&db_conn).await
} }
#[get("contacts")] #[get("contacts")]
pub async fn get_all_contacts(db_conn: web::Data<Arc<PgPool>>) -> TypedHttpResponse<Vec<Contact>> { pub async fn get_all_contacts(db_conn: web::Data<Arc<PgPool>>, request: actix_web::HttpRequest,) -> TypedHttpResponse<Vec<Contact>> {
auth!(request);
services::admin::get_all_contacts(&db_conn).await services::admin::get_all_contacts(&db_conn).await
} }
@ -134,6 +160,18 @@ pub async fn upload_image(
aws_client: web::Data<Arc<aws_sdk_s3::Client>>, aws_client: web::Data<Arc<aws_sdk_s3::Client>>,
path_vars: Path<Item>, path_vars: Path<Item>,
multipart: Multipart, multipart: Multipart,
request: actix_web::HttpRequest,
) -> TypedHttpResponse<String> { ) -> TypedHttpResponse<String> {
auth!(request);
services::admin::upload_image(&aws_client, path_vars.clone(), multipart).await services::admin::upload_image(&aws_client, path_vars.clone(), multipart).await
} }
#[post("auth")]
pub async fn authenticate(
authentication_dto: web::Json<AuthDto>,
) -> TypedHttpResponse<String> {
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."))
}
}

View File

@ -41,7 +41,8 @@ pub async fn start_all_routes(start_time: i64, db_conn: Arc<PgPool>) -> Result<(
.service(super::admin::get_all_contacts) .service(super::admin::get_all_contacts)
.service(super::admin::get_contacts_count) .service(super::admin::get_contacts_count)
.service(super::admin::get_visits_count) .service(super::admin::get_visits_count)
.service(super::admin::upload_image), .service(super::admin::upload_image)
.service(super::admin::authenticate),
) )
.service( .service(
web::scope("/read") web::scope("/read")

23
src/utils/auth.rs Normal file
View File

@ -0,0 +1,23 @@
use std::sync::{RwLock};
use rand::{distributions::Alphanumeric, Rng};
pub static AUTH_TOKEN: RwLock<Option<String>> = RwLock::new(None);
pub fn generate_token(email: &String, password: &String) -> Result<String, ()> {
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<String> {
let lock = AUTH_TOKEN.read().expect("ERROR LOCKING RWLOCK");
lock.clone()
}

View File

@ -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."))),
}
};
}

View File

@ -1,3 +1,4 @@
pub mod macros; pub mod macros;
pub mod s3; pub mod s3;
pub mod visit; pub mod visit;
pub mod auth;