From 6d8319d7849a08fd83de3c50fd30d2c11d275ac6 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 20 Nov 2022 15:43:49 +0100 Subject: [PATCH 1/9] feat: api tests setup --- Cargo.lock | 2 ++ api/Cargo.toml | 6 ++++ api/src/lib.rs | 9 ++++-- api/src/pool.rs | 22 ++++++++----- api/src/routes/admin.rs | 5 +-- api/src/routes/candidate.rs | 5 +-- api/src/test.rs | 40 ++++++++++++++++++++++++ api/tests/candidate.rs | 33 ++++++++++++++++++++ api/tests/common.rs | 62 +++++++++++++++++++++++++++++++++++++ core/src/util.rs | 40 ++++++++++-------------- 10 files changed, 187 insertions(+), 37 deletions(-) create mode 100644 api/src/test.rs create mode 100644 api/tests/candidate.rs create mode 100644 api/tests/common.rs diff --git a/Cargo.lock b/Cargo.lock index 6ae13ce..baa4654 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1981,9 +1981,11 @@ version = "0.1.0" dependencies = [ "async-stream", "async-trait", + "chrono", "dotenv", "futures", "futures-util", + "once_cell", "portfolio-core", "portfolio-entity", "portfolio-migration", diff --git a/api/Cargo.toml b/api/Cargo.toml index ac54819..794181b 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -20,9 +20,15 @@ dotenv = "^0.15" serde_json = { version = "^1.0" } +chrono = "^0.4" + portfolio-entity = { path = "../entity" } portfolio-migration = { path = "../migration" } portfolio-core = { path = "../core" } [dependencies.sea-orm-rocket] version = "^0.5" + + +[dev-dependencies] +once_cell = "1.9.0" \ No newline at end of file diff --git a/api/src/lib.rs b/api/src/lib.rs index 1a793c7..bba53e5 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -12,6 +12,7 @@ mod guards; mod pool; mod requests; mod routes; +pub mod test; use pool::Db; @@ -29,8 +30,7 @@ async fn run_migrations(rocket: Rocket) -> fairing::Result { Ok(rocket) } -#[tokio::main] -async fn start() -> Result<(), rocket::Error> { +pub fn rocket() -> Rocket{ rocket::build() .attach(Db::init()) .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) @@ -80,6 +80,11 @@ async fn start() -> Result<(), rocket::Error> { routes::admin::list_candidates, ]) .register("/", catchers![]) +} + +#[tokio::main] +async fn start() -> Result<(), rocket::Error> { + rocket() .launch() .await .map(|_| ()) diff --git a/api/src/pool.rs b/api/src/pool.rs index b031c6c..650d1c6 100644 --- a/api/src/pool.rs +++ b/api/src/pool.rs @@ -1,4 +1,4 @@ -use portfolio_core::sea_orm; +use portfolio_core::{sea_orm::{self}, util::get_memory_sqlite_connection}; use async_trait::async_trait; use sea_orm::ConnectOptions; @@ -22,20 +22,28 @@ impl sea_orm_rocket::Pool for SeaOrmPool { async fn init(_figment: &Figment) -> Result { dotenv::dotenv().ok(); + if std::env::var("TEST").is_ok() { + let conn = get_memory_sqlite_connection().await; + crate::test::run_test_migrations(&conn).await; + return Ok(Self { conn }); + } + + let database_url = std::env::var("DATABASE_URL").unwrap(); let mut options: ConnectOptions = database_url.into(); options .max_connections(1024) .min_connections(0) .connect_timeout(Duration::from_secs(3)); - - /* options + + /* options .max_connections(config.max_connections as u32) .min_connections(config.min_connections.unwrap_or_default()) .connect_timeout(Duration::from_secs(config.connect_timeout)); - if let Some(idle_timeout) = config.idle_timeout { - options.idle_timeout(Duration::from_secs(idle_timeout)); - } */ + if let Some(idle_timeout) = config.idle_timeout { + options.idle_timeout(Duration::from_secs(idle_timeout)); + } */ + let conn = sea_orm::Database::connect(options).await?; Ok(SeaOrmPool { conn }) @@ -44,4 +52,4 @@ impl sea_orm_rocket::Pool for SeaOrmPool { fn borrow(&self) -> &Self::Connection { &self.conn } -} +} \ No newline at end of file diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs index e4eb796..9bc68ac 100644 --- a/api/src/routes/admin.rs +++ b/api/src/routes/admin.rs @@ -1,4 +1,4 @@ -use std::net::SocketAddr; +use std::net::{SocketAddr, IpAddr, Ipv4Addr}; use portfolio_core::{ crypto::random_8_char_string, @@ -17,9 +17,10 @@ use crate::{guards::request::auth::AdminAuth, pool::Db, requests}; pub async fn login( conn: Connection<'_, Db>, login_form: Json, - ip_addr: SocketAddr, + // ip_addr: SocketAddr, // TODO uncomment in production cookies: &CookieJar<'_>, ) -> Result> { + let ip_addr: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0); let db = conn.into_inner(); let session_token_key = AdminService::login( db, diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index e180352..2175b5d 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -1,4 +1,4 @@ -use std::net::SocketAddr; +use std::net::{SocketAddr, IpAddr, Ipv4Addr}; use portfolio_core::candidate_details::ApplicationDetails; use portfolio_core::services::application_service::ApplicationService; @@ -19,9 +19,10 @@ use crate::{guards::request::auth::CandidateAuth, pool::Db, requests}; pub async fn login( conn: Connection<'_, Db>, login_form: Json, - ip_addr: SocketAddr, + // ip_addr: SocketAddr, // TODO uncomment in production cookies: &CookieJar<'_>, ) -> Result> { + let ip_addr: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0); let db = conn.into_inner(); let session_token_key = CandidateService::login( db, diff --git a/api/src/test.rs b/api/src/test.rs new file mode 100644 index 0000000..2ce5bde --- /dev/null +++ b/api/src/test.rs @@ -0,0 +1,40 @@ +use entity::admin; +use portfolio_core::{sea_orm::{DbConn, Set, ActiveModelTrait}, crypto, services::application_service::ApplicationService}; + +pub const ADMIN_ID: i32 = 1; +pub const ADMIN_PASSWORD: &'static str = "test"; + +pub const APPLICATION_ID: i32 = 103151; +pub const CANDIDATE_PASSWORD: &'static str = "test"; +pub const PERSONAL_ID_NUMBER: &'static str = "0101010000"; + +pub async fn run_test_migrations(db: &DbConn) { + let (pubkey, priv_key) = crypto::create_identity(); + let priv_key = crypto::encrypt_password( + priv_key, + ADMIN_PASSWORD.to_string() + ).await.unwrap(); + let password_hash = crypto::hash_password(ADMIN_PASSWORD.to_string()).await.unwrap(); + + admin::ActiveModel { + id: Set(ADMIN_ID), + name: Set("admin pepa".to_string()), + public_key: Set(pubkey), + private_key: Set(priv_key), + password: Set(password_hash), + created_at: Set(chrono::Utc::now().naive_utc()), + updated_at: Set(chrono::Utc::now().naive_utc()), + } + .insert(db) + .await + .unwrap(); + + ApplicationService::create_candidate_with_parent( + db, + APPLICATION_ID, + &CANDIDATE_PASSWORD.to_string(), + PERSONAL_ID_NUMBER.to_string() + ) + .await + .unwrap(); +} \ No newline at end of file diff --git a/api/tests/candidate.rs b/api/tests/candidate.rs new file mode 100644 index 0000000..4d47a0c --- /dev/null +++ b/api/tests/candidate.rs @@ -0,0 +1,33 @@ +mod common; +use common::*; +use portfolio_api::test::APPLICATION_ID; +use rocket::http::Status; + +#[test] +fn test_login_valid_credentials() { + let client = test_client().lock().unwrap(); + let _response = candidate_login(&client); +} + +#[test] +fn test_create_candidate() { + let client = test_client().lock().unwrap(); + let cookies = admin_login(&client); + let password = create_candidate(&client, cookies, 1031511, "0".to_string()); + + assert_eq!(password.len(), 8); +} + +#[test] +fn test_auth_candidate() { + let client = test_client().lock().unwrap(); + let cookies = candidate_login(&client); + let response = client + .get("/candidate/whoami") + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + assert_eq!(response.into_string().unwrap(), APPLICATION_ID.to_string()); +} \ No newline at end of file diff --git a/api/tests/common.rs b/api/tests/common.rs new file mode 100644 index 0000000..1214b48 --- /dev/null +++ b/api/tests/common.rs @@ -0,0 +1,62 @@ +use once_cell::sync::OnceCell; +use std::sync::Mutex; +use rocket::http::{Cookie, Status}; +use rocket::local::blocking::{Client}; +use portfolio_api::rocket; + +use portfolio_api::test::{ADMIN_ID, ADMIN_PASSWORD, APPLICATION_ID, CANDIDATE_PASSWORD}; + +pub fn test_client() -> &'static Mutex { + static INSTANCE: OnceCell> = OnceCell::new(); + INSTANCE.get_or_init(|| { + let rocket = rocket(); + Mutex::from(Client::tracked(rocket).expect("valid rocket instance")) + }) +} + +pub fn candidate_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/candidate/login") + .body(format!("{{ + \"application_id\": {}, + \"password\": \"{}\" + }}", APPLICATION_ID, CANDIDATE_PASSWORD)) + .dispatch(); + + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned() + ) +} + +pub fn admin_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/admin/login") + .body(format!("{{ + \"admin_id\": {}, + \"password\": \"{}\" + }}", ADMIN_ID, ADMIN_PASSWORD)) + .dispatch(); + + println!("{:?}", response); + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) +} + +pub fn create_candidate(client: &Client, cookies: (Cookie, Cookie), id: i32, pid: String) -> String { + let response = client + .post("/admin/create") + .body(format!("{{ + \"application_id\": {}, + \"personal_id_number\": \"{}\" + }}", id, pid)) + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + response.into_string().unwrap() +} \ No newline at end of file diff --git a/core/src/util.rs b/core/src/util.rs index ab47922..a988644 100644 --- a/core/src/util.rs +++ b/core/src/util.rs @@ -1,30 +1,22 @@ -#[cfg(test)] +use entity::{admin, candidate, parent, session}; +use sea_orm::{Schema, Database, DbConn}; +use sea_orm::{sea_query::TableCreateStatement, ConnectionTrait, DbBackend}; + + pub async fn get_memory_sqlite_connection() -> sea_orm::DbConn { - use entity::{admin, candidate, parent, session}; - use sea_orm::{Schema, Database, DbConn}; - use sea_orm::{sea_query::TableCreateStatement, ConnectionTrait, DbBackend}; - let base_url = "sqlite::memory:"; - let db: DbConn = Database::connect(base_url).await.unwrap(); + let db: DbConn = Database::connect(base_url).await.unwrap(); - let schema = Schema::new(DbBackend::Sqlite); - let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity); - let stmt2: TableCreateStatement = schema.create_table_from_entity(admin::Entity); - let stmt3: TableCreateStatement = schema.create_table_from_entity(session::Entity); - let stmt4: TableCreateStatement = schema.create_table_from_entity(parent::Entity); - db.execute(db.get_database_backend().build(&stmt)) - .await - .unwrap(); - db.execute(db.get_database_backend().build(&stmt2)) - .await - .unwrap(); - db.execute(db.get_database_backend().build(&stmt3)) - .await - .unwrap(); - db.execute(db.get_database_backend().build(&stmt4)) - .await - .unwrap(); - db + let schema = Schema::new(DbBackend::Sqlite); + let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity); + let stmt2: TableCreateStatement = schema.create_table_from_entity(admin::Entity); + let stmt3: TableCreateStatement = schema.create_table_from_entity(session::Entity); + let stmt4: TableCreateStatement = schema.create_table_from_entity(parent::Entity); + db.execute(db.get_database_backend().build(&stmt)).await.unwrap(); + db.execute(db.get_database_backend().build(&stmt2)).await.unwrap(); + db.execute(db.get_database_backend().build(&stmt3)).await.unwrap(); + db.execute(db.get_database_backend().build(&stmt4)).await.unwrap(); + db } #[cfg(test)] From 2b5e8c107515fbde19dba6b4387ddffbcd4a81a1 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 20 Nov 2022 15:46:32 +0100 Subject: [PATCH 2/9] refactor: change env var name to 'TEST_API' --- api/src/pool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/pool.rs b/api/src/pool.rs index 650d1c6..2951fa2 100644 --- a/api/src/pool.rs +++ b/api/src/pool.rs @@ -22,7 +22,7 @@ impl sea_orm_rocket::Pool for SeaOrmPool { async fn init(_figment: &Figment) -> Result { dotenv::dotenv().ok(); - if std::env::var("TEST").is_ok() { + if std::env::var("TEST_API").is_ok() { let conn = get_memory_sqlite_connection().await; crate::test::run_test_migrations(&conn).await; return Ok(Self { conn }); From 8656a82ef84f94e57ddacceef45b21915ffeb1c3 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 20 Nov 2022 15:47:25 +0100 Subject: [PATCH 3/9] devops: run api tests --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a9edd92..b9e9704 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -7,6 +7,7 @@ on: env: CARGO_TERM_COLOR: always + TEST_API: true jobs: build: From 1bfc8f68c26c07c757bbc27788b765777274bd1d Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 20 Nov 2022 21:17:08 +0100 Subject: [PATCH 4/9] feat: return 401 error instead of panicking --- core/src/error.rs | 3 +++ core/src/services/admin_service.rs | 2 +- core/src/services/candidate_service.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/error.rs b/core/src/error.rs index 206d579..8c34271 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -8,6 +8,8 @@ pub enum ServiceError { InvalidApplicationId, #[error("Invalid credentials")] InvalidCredentials, + #[error("Unauthorized")] + Unauthorized, #[error("Forbidden")] Forbidden, #[error("Session expired, please login agai")] @@ -65,6 +67,7 @@ impl ServiceError { match self { ServiceError::InvalidApplicationId => 400, ServiceError::InvalidCredentials => 401, + ServiceError::Unauthorized => 401, ServiceError::Forbidden => 403, ServiceError::ExpiredSession => 401, ServiceError::JwtError => 500, diff --git a/core/src/services/admin_service.rs b/core/src/services/admin_service.rs index 76c719a..9e23b65 100644 --- a/core/src/services/admin_service.rs +++ b/core/src/services/admin_service.rs @@ -41,7 +41,7 @@ impl AdminService { pub async fn auth(db: &DbConn, session_uuid: Uuid) -> Result { match SessionService::auth_user_session(db, session_uuid).await? { AdminUser::Admin(admin) => Ok(admin), - AdminUser::Candidate(_) => unreachable!(), + AdminUser::Candidate(_) => Err(ServiceError::Unauthorized), } } } diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 9c12b72..b5ca5e0 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -215,7 +215,7 @@ impl CandidateService { match SessionService::auth_user_session(db, session_uuid).await { Ok(user) => match user { AdminUser::Candidate(candidate) => Ok(candidate), - AdminUser::Admin(_) => unreachable!(), + AdminUser::Admin(_) => Err(ServiceError::Unauthorized), }, Err(e) => Err(e), } From b8ae1a898d6dc743e6cfe6280e5214f1e78d2023 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 20 Nov 2022 21:17:45 +0100 Subject: [PATCH 5/9] feat: candidate endpoints tests --- api/tests/candidate.rs | 108 +++++++++++++++++++++++++++++++++- core/src/candidate_details.rs | 2 +- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/api/tests/candidate.rs b/api/tests/candidate.rs index 4d47a0c..68d5981 100644 --- a/api/tests/candidate.rs +++ b/api/tests/candidate.rs @@ -1,7 +1,26 @@ mod common; use common::*; use portfolio_api::test::APPLICATION_ID; -use rocket::http::Status; +use portfolio_core::{candidate_details::ApplicationDetails, sea_orm::prelude::Uuid, crypto}; +use rocket::{http::{Status, Cookie}}; + + +const CANDIDATE_DETAILS: &'static str = "{ + \"name\": \"idk\", + \"surname\": \"idk\", + \"birthplace\": \"Praha 1\", + \"birthdate\": \"2015-09-18\", + \"address\": \"Stefanikova jidelna\", + \"telephone\": \"000111222333\", + \"citizenship\": \"Czech Republic\", + \"email\": \"magor@magor.cz\", + \"sex\": \"MALE\", + \"study\": \"KB\", + \"parent_name\": \"maminka\", + \"parent_surname\": \"chad\", + \"parent_telephone\": \"420111222333\", + \"parent_email\": \"maminka@centrum.cz\" +}"; #[test] fn test_login_valid_credentials() { @@ -30,4 +49,91 @@ fn test_auth_candidate() { assert_eq!(response.status(), Status::Ok); assert_eq!(response.into_string().unwrap(), APPLICATION_ID.to_string()); +} + +#[test] +fn test_add_get_candidate_details() { + let client = test_client().lock().unwrap(); + let cookies = candidate_login(&client); + + let details_orig: ApplicationDetails = serde_json::from_str(CANDIDATE_DETAILS).unwrap(); + + let response = client + .post("/candidate/add/details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = client + .post("/candidate/get_details") + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let details_resp: ApplicationDetails = serde_json::from_str(&response.into_string().unwrap()).unwrap(); + assert_eq!(details_orig, details_resp); +} + +#[test] +fn test_invalid_token_every_secured_endpoint() { + let client = test_client().lock().unwrap(); + + let id = Cookie::new("id", Uuid::new_v4().to_string()); + let (private_key, _) = crypto::create_identity(); + let key = Cookie::new("key", private_key); + + let response = client + .post("/candidate/add/details") + .cookie(id.clone()) + .cookie(key.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .post("/candidate/get_details") + .cookie(id.clone()) + .cookie(key.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .get("/candidate/whoami") + .cookie(id.clone()) + .cookie(key.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); +} + +#[test] +fn test_admin_token_on_secured_candidate_endpoints() { + let client = test_client().lock().unwrap(); + let cookies = admin_login(&client); + + let response = client + .post("/candidate/add/details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .post("/candidate/get_details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .get("/candidate/whoami") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); } \ No newline at end of file diff --git a/core/src/candidate_details.rs b/core/src/candidate_details.rs index 47c483e..ea4616a 100644 --- a/core/src/candidate_details.rs +++ b/core/src/candidate_details.rs @@ -185,7 +185,7 @@ impl TryFrom<(candidate::Model, parent::Model)> for EncryptedApplicationDetails } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct ApplicationDetails { // Candidate pub name: String, From 970c8315d1ed493e266a4cc91f205954d7953926 Mon Sep 17 00:00:00 2001 From: EETagent Date: Mon, 21 Nov 2022 17:36:37 +0100 Subject: [PATCH 6/9] refactor: rework api tests --- .github/workflows/rust.yml | 1 - api/src/pool.rs | 14 ++-- api/src/routes/candidate.rs | 141 +++++++++++++++++++++++++++++++++++ api/src/test.rs | 144 ++++++++++++++++++++++++++++-------- api/tests/candidate.rs | 139 ---------------------------------- api/tests/common.rs | 62 ---------------- 6 files changed, 263 insertions(+), 238 deletions(-) delete mode 100644 api/tests/candidate.rs delete mode 100644 api/tests/common.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b9e9704..a9edd92 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -7,7 +7,6 @@ on: env: CARGO_TERM_COLOR: always - TEST_API: true jobs: build: diff --git a/api/src/pool.rs b/api/src/pool.rs index 2951fa2..280b0c6 100644 --- a/api/src/pool.rs +++ b/api/src/pool.rs @@ -20,14 +20,16 @@ impl sea_orm_rocket::Pool for SeaOrmPool { type Connection = sea_orm::DatabaseConnection; + #[cfg(test)] + async fn init(_figment: &Figment) -> Result { + let conn = get_memory_sqlite_connection().await; + crate::test::tests::run_test_migrations(&conn).await; + return Ok(Self { conn }); + } + + #[cfg(not(test))] async fn init(_figment: &Figment) -> Result { dotenv::dotenv().ok(); - if std::env::var("TEST_API").is_ok() { - let conn = get_memory_sqlite_connection().await; - crate::test::run_test_migrations(&conn).await; - return Ok(Self { conn }); - } - let database_url = std::env::var("DATABASE_URL").unwrap(); let mut options: ConnectOptions = database_url.into(); diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index 2175b5d..0076602 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -283,4 +283,145 @@ pub async fn download_portfolio(session: CandidateAuth) -> Result, Custo } Ok(file.unwrap()) +} + +#[cfg(test)] +mod tests { + use portfolio_core::{candidate_details::ApplicationDetails, sea_orm::prelude::Uuid, crypto}; + use rocket::http::{Status, Cookie}; + + use crate::test::tests::{create_candidate, admin_login, test_client, candidate_login, APPLICATION_ID}; + + const CANDIDATE_DETAILS: &'static str = "{ + \"name\": \"idk\", + \"surname\": \"idk\", + \"birthplace\": \"Praha 1\", + \"birthdate\": \"2015-09-18\", + \"address\": \"Stefanikova jidelna\", + \"telephone\": \"000111222333\", + \"citizenship\": \"Czech Republic\", + \"email\": \"magor@magor.cz\", + \"sex\": \"MALE\", + \"study\": \"KB\", + \"parent_name\": \"maminka\", + \"parent_surname\": \"chad\", + \"parent_telephone\": \"420111222333\", + \"parent_email\": \"maminka@centrum.cz\" + }"; + + #[test] + fn test_login_valid_credentials() { + let client = test_client().lock().unwrap(); + let _response = candidate_login(&client); + } + + #[test] + fn test_create_candidate() { + let client = test_client().lock().unwrap(); + let cookies = admin_login(&client); + let password = create_candidate(&client, cookies, 1031511, "0".to_string()); + + assert_eq!(password.len(), 8); + } + + #[test] + fn test_auth_candidate() { + let client = test_client().lock().unwrap(); + let cookies = candidate_login(&client); + let response = client + .get("/candidate/whoami") + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + assert_eq!(response.into_string().unwrap(), APPLICATION_ID.to_string()); + } + + #[test] + fn test_add_get_candidate_details() { + let client = test_client().lock().unwrap(); + let cookies = candidate_login(&client); + + let details_orig: ApplicationDetails = serde_json::from_str(CANDIDATE_DETAILS).unwrap(); + + let response = client + .post("/candidate/add/details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let response = client + .post("/candidate/get_details") + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + let details_resp: ApplicationDetails = serde_json::from_str(&response.into_string().unwrap()).unwrap(); + assert_eq!(details_orig, details_resp); + } + + #[test] + fn test_invalid_token_every_secured_endpoint() { + let client = test_client().lock().unwrap(); + + let id = Cookie::new("id", Uuid::new_v4().to_string()); + let (private_key, _) = crypto::create_identity(); + let key = Cookie::new("key", private_key); + + let response = client + .post("/candidate/add/details") + .cookie(id.clone()) + .cookie(key.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .post("/candidate/get_details") + .cookie(id.clone()) + .cookie(key.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .get("/candidate/whoami") + .cookie(id.clone()) + .cookie(key.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + } + + #[test] + fn test_admin_token_on_secured_candidate_endpoints() { + let client = test_client().lock().unwrap(); + let cookies = admin_login(&client); + + let response = client + .post("/candidate/add/details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .body(CANDIDATE_DETAILS.to_string()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .post("/candidate/get_details") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + + let response = client + .get("/candidate/whoami") + .cookie(cookies.0.clone()) + .cookie(cookies.1.clone()) + .dispatch(); + assert_eq!(response.status(), Status::Unauthorized); + } } \ No newline at end of file diff --git a/api/src/test.rs b/api/src/test.rs index 2ce5bde..b1db8f9 100644 --- a/api/src/test.rs +++ b/api/src/test.rs @@ -1,40 +1,124 @@ -use entity::admin; -use portfolio_core::{sea_orm::{DbConn, Set, ActiveModelTrait}, crypto, services::application_service::ApplicationService}; +#[cfg(test)] +pub mod tests { + use crate::rocket; + use entity::admin; + use once_cell::sync::OnceCell; + use portfolio_core::{ + crypto, + sea_orm::{ActiveModelTrait, DbConn, Set}, + services::application_service::ApplicationService, + }; + use rocket::{ + http::{Cookie, Status}, + local::blocking::Client, + }; + use std::sync::Mutex; -pub const ADMIN_ID: i32 = 1; -pub const ADMIN_PASSWORD: &'static str = "test"; + pub const ADMIN_ID: i32 = 1; + pub const ADMIN_PASSWORD: &'static str = "test"; -pub const APPLICATION_ID: i32 = 103151; -pub const CANDIDATE_PASSWORD: &'static str = "test"; -pub const PERSONAL_ID_NUMBER: &'static str = "0101010000"; + pub const APPLICATION_ID: i32 = 103151; + pub const CANDIDATE_PASSWORD: &'static str = "test"; + pub const PERSONAL_ID_NUMBER: &'static str = "0101010000"; -pub async fn run_test_migrations(db: &DbConn) { - let (pubkey, priv_key) = crypto::create_identity(); - let priv_key = crypto::encrypt_password( - priv_key, - ADMIN_PASSWORD.to_string() - ).await.unwrap(); - let password_hash = crypto::hash_password(ADMIN_PASSWORD.to_string()).await.unwrap(); + pub async fn run_test_migrations(db: &DbConn) { + let (pubkey, priv_key) = crypto::create_identity(); + let priv_key = crypto::encrypt_password(priv_key, ADMIN_PASSWORD.to_string()) + .await + .unwrap(); + let password_hash = crypto::hash_password(ADMIN_PASSWORD.to_string()) + .await + .unwrap(); - admin::ActiveModel { - id: Set(ADMIN_ID), - name: Set("admin pepa".to_string()), - public_key: Set(pubkey), - private_key: Set(priv_key), - password: Set(password_hash), - created_at: Set(chrono::Utc::now().naive_utc()), - updated_at: Set(chrono::Utc::now().naive_utc()), - } + admin::ActiveModel { + id: Set(ADMIN_ID), + name: Set("admin pepa".to_string()), + public_key: Set(pubkey), + private_key: Set(priv_key), + password: Set(password_hash), + created_at: Set(chrono::Utc::now().naive_utc()), + updated_at: Set(chrono::Utc::now().naive_utc()), + } .insert(db) .await .unwrap(); - ApplicationService::create_candidate_with_parent( - db, - APPLICATION_ID, - &CANDIDATE_PASSWORD.to_string(), - PERSONAL_ID_NUMBER.to_string() - ) + ApplicationService::create_candidate_with_parent( + db, + APPLICATION_ID, + &CANDIDATE_PASSWORD.to_string(), + PERSONAL_ID_NUMBER.to_string(), + ) .await .unwrap(); -} \ No newline at end of file + } + + pub fn test_client() -> &'static Mutex { + static INSTANCE: OnceCell> = OnceCell::new(); + INSTANCE.get_or_init(|| { + let rocket = rocket(); + Mutex::from(Client::tracked(rocket).expect("valid rocket instance")) + }) + } + + pub fn candidate_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/candidate/login") + .body(format!( + "{{ + \"application_id\": {}, + \"password\": \"{}\" + }}", + APPLICATION_ID, CANDIDATE_PASSWORD + )) + .dispatch(); + + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) + } + + pub fn admin_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/admin/login") + .body(format!( + "{{ + \"admin_id\": {}, + \"password\": \"{}\" + }}", + ADMIN_ID, ADMIN_PASSWORD + )) + .dispatch(); + + println!("{:?}", response); + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) + } + + pub fn create_candidate( + client: &Client, + cookies: (Cookie, Cookie), + id: i32, + pid: String, + ) -> String { + let response = client + .post("/admin/create") + .body(format!( + "{{ + \"application_id\": {}, + \"personal_id_number\": \"{}\" + }}", + id, pid + )) + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + response.into_string().unwrap() + } +} diff --git a/api/tests/candidate.rs b/api/tests/candidate.rs deleted file mode 100644 index 68d5981..0000000 --- a/api/tests/candidate.rs +++ /dev/null @@ -1,139 +0,0 @@ -mod common; -use common::*; -use portfolio_api::test::APPLICATION_ID; -use portfolio_core::{candidate_details::ApplicationDetails, sea_orm::prelude::Uuid, crypto}; -use rocket::{http::{Status, Cookie}}; - - -const CANDIDATE_DETAILS: &'static str = "{ - \"name\": \"idk\", - \"surname\": \"idk\", - \"birthplace\": \"Praha 1\", - \"birthdate\": \"2015-09-18\", - \"address\": \"Stefanikova jidelna\", - \"telephone\": \"000111222333\", - \"citizenship\": \"Czech Republic\", - \"email\": \"magor@magor.cz\", - \"sex\": \"MALE\", - \"study\": \"KB\", - \"parent_name\": \"maminka\", - \"parent_surname\": \"chad\", - \"parent_telephone\": \"420111222333\", - \"parent_email\": \"maminka@centrum.cz\" -}"; - -#[test] -fn test_login_valid_credentials() { - let client = test_client().lock().unwrap(); - let _response = candidate_login(&client); -} - -#[test] -fn test_create_candidate() { - let client = test_client().lock().unwrap(); - let cookies = admin_login(&client); - let password = create_candidate(&client, cookies, 1031511, "0".to_string()); - - assert_eq!(password.len(), 8); -} - -#[test] -fn test_auth_candidate() { - let client = test_client().lock().unwrap(); - let cookies = candidate_login(&client); - let response = client - .get("/candidate/whoami") - .cookie(cookies.0) - .cookie(cookies.1) - .dispatch(); - - assert_eq!(response.status(), Status::Ok); - assert_eq!(response.into_string().unwrap(), APPLICATION_ID.to_string()); -} - -#[test] -fn test_add_get_candidate_details() { - let client = test_client().lock().unwrap(); - let cookies = candidate_login(&client); - - let details_orig: ApplicationDetails = serde_json::from_str(CANDIDATE_DETAILS).unwrap(); - - let response = client - .post("/candidate/add/details") - .cookie(cookies.0.clone()) - .cookie(cookies.1.clone()) - .body(CANDIDATE_DETAILS.to_string()) - .dispatch(); - - assert_eq!(response.status(), Status::Ok); - - let response = client - .post("/candidate/get_details") - .cookie(cookies.0) - .cookie(cookies.1) - .dispatch(); - - assert_eq!(response.status(), Status::Ok); - - let details_resp: ApplicationDetails = serde_json::from_str(&response.into_string().unwrap()).unwrap(); - assert_eq!(details_orig, details_resp); -} - -#[test] -fn test_invalid_token_every_secured_endpoint() { - let client = test_client().lock().unwrap(); - - let id = Cookie::new("id", Uuid::new_v4().to_string()); - let (private_key, _) = crypto::create_identity(); - let key = Cookie::new("key", private_key); - - let response = client - .post("/candidate/add/details") - .cookie(id.clone()) - .cookie(key.clone()) - .body(CANDIDATE_DETAILS.to_string()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); - - let response = client - .post("/candidate/get_details") - .cookie(id.clone()) - .cookie(key.clone()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); - - let response = client - .get("/candidate/whoami") - .cookie(id.clone()) - .cookie(key.clone()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); -} - -#[test] -fn test_admin_token_on_secured_candidate_endpoints() { - let client = test_client().lock().unwrap(); - let cookies = admin_login(&client); - - let response = client - .post("/candidate/add/details") - .cookie(cookies.0.clone()) - .cookie(cookies.1.clone()) - .body(CANDIDATE_DETAILS.to_string()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); - - let response = client - .post("/candidate/get_details") - .cookie(cookies.0.clone()) - .cookie(cookies.1.clone()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); - - let response = client - .get("/candidate/whoami") - .cookie(cookies.0.clone()) - .cookie(cookies.1.clone()) - .dispatch(); - assert_eq!(response.status(), Status::Unauthorized); -} \ No newline at end of file diff --git a/api/tests/common.rs b/api/tests/common.rs deleted file mode 100644 index 1214b48..0000000 --- a/api/tests/common.rs +++ /dev/null @@ -1,62 +0,0 @@ -use once_cell::sync::OnceCell; -use std::sync::Mutex; -use rocket::http::{Cookie, Status}; -use rocket::local::blocking::{Client}; -use portfolio_api::rocket; - -use portfolio_api::test::{ADMIN_ID, ADMIN_PASSWORD, APPLICATION_ID, CANDIDATE_PASSWORD}; - -pub fn test_client() -> &'static Mutex { - static INSTANCE: OnceCell> = OnceCell::new(); - INSTANCE.get_or_init(|| { - let rocket = rocket(); - Mutex::from(Client::tracked(rocket).expect("valid rocket instance")) - }) -} - -pub fn candidate_login(client: &Client) -> (Cookie, Cookie) { - let response = client - .post("/candidate/login") - .body(format!("{{ - \"application_id\": {}, - \"password\": \"{}\" - }}", APPLICATION_ID, CANDIDATE_PASSWORD)) - .dispatch(); - - ( - response.cookies().get("id").unwrap().to_owned(), - response.cookies().get("key").unwrap().to_owned() - ) -} - -pub fn admin_login(client: &Client) -> (Cookie, Cookie) { - let response = client - .post("/admin/login") - .body(format!("{{ - \"admin_id\": {}, - \"password\": \"{}\" - }}", ADMIN_ID, ADMIN_PASSWORD)) - .dispatch(); - - println!("{:?}", response); - ( - response.cookies().get("id").unwrap().to_owned(), - response.cookies().get("key").unwrap().to_owned(), - ) -} - -pub fn create_candidate(client: &Client, cookies: (Cookie, Cookie), id: i32, pid: String) -> String { - let response = client - .post("/admin/create") - .body(format!("{{ - \"application_id\": {}, - \"personal_id_number\": \"{}\" - }}", id, pid)) - .cookie(cookies.0) - .cookie(cookies.1) - .dispatch(); - - assert_eq!(response.status(), Status::Ok); - - response.into_string().unwrap() -} \ No newline at end of file From 004125b332d97487ab3e65fd81ddb0c082bbc0ba Mon Sep 17 00:00:00 2001 From: EETagent Date: Mon, 21 Nov 2022 17:39:39 +0100 Subject: [PATCH 7/9] fix: hide unused errors --- api/src/pool.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/src/pool.rs b/api/src/pool.rs index 280b0c6..d3a45a6 100644 --- a/api/src/pool.rs +++ b/api/src/pool.rs @@ -1,8 +1,9 @@ -use portfolio_core::{sea_orm::{self}, util::get_memory_sqlite_connection}; - +use portfolio_core::{sea_orm::{self}}; use async_trait::async_trait; +#[cfg(not(test))] use sea_orm::ConnectOptions; use sea_orm_rocket::{rocket::figment::Figment, Database}; +#[cfg(not(test))] use std::time::Duration; #[derive(Database, Debug)] @@ -22,7 +23,7 @@ impl sea_orm_rocket::Pool for SeaOrmPool { #[cfg(test)] async fn init(_figment: &Figment) -> Result { - let conn = get_memory_sqlite_connection().await; + let conn = portfolio_core::util::get_memory_sqlite_connection().await; crate::test::tests::run_test_migrations(&conn).await; return Ok(Self { conn }); } From cdf75d3eec2510cefa3610bee0521598bf617e14 Mon Sep 17 00:00:00 2001 From: EETagent Date: Mon, 21 Nov 2022 17:49:22 +0100 Subject: [PATCH 8/9] refactor: move admin tests to admin route --- api/src/routes/admin.rs | 59 ++++++++++++++++++++ api/src/routes/candidate.rs | 108 +++++++++++++++++++++++------------- api/src/test.rs | 62 --------------------- 3 files changed, 127 insertions(+), 102 deletions(-) diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs index 9bc68ac..a3d6efc 100644 --- a/api/src/routes/admin.rs +++ b/api/src/routes/admin.rs @@ -156,4 +156,63 @@ pub async fn get_candidate_portfolio( .map_err(|e| Custom(Status::from_code(e.code()).unwrap(), e.to_string()))?; Ok(portfolio) +} + +#[cfg(test)] +mod tests { + use rocket::{local::blocking::Client, http::{Cookie, Status}}; + + use crate::test::tests::{test_client, ADMIN_PASSWORD, ADMIN_ID}; + + fn admin_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/admin/login") + .body(format!( + "{{ + \"admin_id\": {}, + \"password\": \"{}\" + }}", + ADMIN_ID, ADMIN_PASSWORD + )) + .dispatch(); + + println!("{:?}", response); + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) + } + + fn create_candidate( + client: &Client, + cookies: (Cookie, Cookie), + id: i32, + pid: String, + ) -> String { + let response = client + .post("/admin/create") + .body(format!( + "{{ + \"application_id\": {}, + \"personal_id_number\": \"{}\" + }}", + id, pid + )) + .cookie(cookies.0) + .cookie(cookies.1) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + + response.into_string().unwrap() + } + + #[test] + fn test_create_candidate() { + let client = test_client().lock().unwrap(); + let cookies = admin_login(&client); + let password = create_candidate(&client, cookies, 1031511, "0".to_string()); + + assert_eq!(password.len(), 8); + } } \ No newline at end of file diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index 0076602..e83252a 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -1,4 +1,4 @@ -use std::net::{SocketAddr, IpAddr, Ipv4Addr}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use portfolio_core::candidate_details::ApplicationDetails; use portfolio_core::services::application_service::ApplicationService; @@ -85,18 +85,14 @@ pub async fn add_details( #[post("/get_details")] pub async fn get_details( conn: Connection<'_, Db>, - session: CandidateAuth + session: CandidateAuth, ) -> Result, Custom> { let db = conn.into_inner(); let private_key = session.get_private_key(); let candidate: entity::candidate::Model = session.into(); - // let handle = tokio::spawn(async move { - let details = ApplicationService::decrypt_all_details(private_key, - db, - candidate.application - ) + let details = ApplicationService::decrypt_all_details(private_key, db, candidate.application) .await .map_err(|e| { Custom( @@ -287,10 +283,50 @@ pub async fn download_portfolio(session: CandidateAuth) -> Result, Custo #[cfg(test)] mod tests { - use portfolio_core::{candidate_details::ApplicationDetails, sea_orm::prelude::Uuid, crypto}; - use rocket::http::{Status, Cookie}; + use portfolio_core::{candidate_details::ApplicationDetails, crypto, sea_orm::prelude::Uuid}; + use rocket::{ + http::{Cookie, Status}, + local::blocking::Client, + }; - use crate::test::tests::{create_candidate, admin_login, test_client, candidate_login, APPLICATION_ID}; + use crate::test::tests::{test_client, APPLICATION_ID, CANDIDATE_PASSWORD, ADMIN_PASSWORD, ADMIN_ID}; + + fn candidate_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/candidate/login") + .body(format!( + "{{ + \"application_id\": {}, + \"password\": \"{}\" + }}", + APPLICATION_ID, CANDIDATE_PASSWORD + )) + .dispatch(); + + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) + } + + fn admin_login(client: &Client) -> (Cookie, Cookie) { + let response = client + .post("/admin/login") + .body(format!( + "{{ + \"admin_id\": {}, + \"password\": \"{}\" + }}", + ADMIN_ID, ADMIN_PASSWORD + )) + .dispatch(); + + println!("{:?}", response); + ( + response.cookies().get("id").unwrap().to_owned(), + response.cookies().get("key").unwrap().to_owned(), + ) + } const CANDIDATE_DETAILS: &'static str = "{ \"name\": \"idk\", @@ -308,22 +344,13 @@ mod tests { \"parent_telephone\": \"420111222333\", \"parent_email\": \"maminka@centrum.cz\" }"; - + #[test] fn test_login_valid_credentials() { let client = test_client().lock().unwrap(); let _response = candidate_login(&client); } - - #[test] - fn test_create_candidate() { - let client = test_client().lock().unwrap(); - let cookies = admin_login(&client); - let password = create_candidate(&client, cookies, 1031511, "0".to_string()); - - assert_eq!(password.len(), 8); - } - + #[test] fn test_auth_candidate() { let client = test_client().lock().unwrap(); @@ -333,47 +360,48 @@ mod tests { .cookie(cookies.0) .cookie(cookies.1) .dispatch(); - + assert_eq!(response.status(), Status::Ok); assert_eq!(response.into_string().unwrap(), APPLICATION_ID.to_string()); } - + #[test] fn test_add_get_candidate_details() { let client = test_client().lock().unwrap(); let cookies = candidate_login(&client); - + let details_orig: ApplicationDetails = serde_json::from_str(CANDIDATE_DETAILS).unwrap(); - + let response = client .post("/candidate/add/details") .cookie(cookies.0.clone()) .cookie(cookies.1.clone()) .body(CANDIDATE_DETAILS.to_string()) .dispatch(); - + assert_eq!(response.status(), Status::Ok); - + let response = client .post("/candidate/get_details") .cookie(cookies.0) .cookie(cookies.1) .dispatch(); - + assert_eq!(response.status(), Status::Ok); - - let details_resp: ApplicationDetails = serde_json::from_str(&response.into_string().unwrap()).unwrap(); + + let details_resp: ApplicationDetails = + serde_json::from_str(&response.into_string().unwrap()).unwrap(); assert_eq!(details_orig, details_resp); } - + #[test] fn test_invalid_token_every_secured_endpoint() { let client = test_client().lock().unwrap(); - + let id = Cookie::new("id", Uuid::new_v4().to_string()); let (private_key, _) = crypto::create_identity(); let key = Cookie::new("key", private_key); - + let response = client .post("/candidate/add/details") .cookie(id.clone()) @@ -381,14 +409,14 @@ mod tests { .body(CANDIDATE_DETAILS.to_string()) .dispatch(); assert_eq!(response.status(), Status::Unauthorized); - + let response = client .post("/candidate/get_details") .cookie(id.clone()) .cookie(key.clone()) .dispatch(); assert_eq!(response.status(), Status::Unauthorized); - + let response = client .get("/candidate/whoami") .cookie(id.clone()) @@ -396,12 +424,12 @@ mod tests { .dispatch(); assert_eq!(response.status(), Status::Unauthorized); } - + #[test] fn test_admin_token_on_secured_candidate_endpoints() { let client = test_client().lock().unwrap(); let cookies = admin_login(&client); - + let response = client .post("/candidate/add/details") .cookie(cookies.0.clone()) @@ -409,14 +437,14 @@ mod tests { .body(CANDIDATE_DETAILS.to_string()) .dispatch(); assert_eq!(response.status(), Status::Unauthorized); - + let response = client .post("/candidate/get_details") .cookie(cookies.0.clone()) .cookie(cookies.1.clone()) .dispatch(); assert_eq!(response.status(), Status::Unauthorized); - + let response = client .get("/candidate/whoami") .cookie(cookies.0.clone()) @@ -424,4 +452,4 @@ mod tests { .dispatch(); assert_eq!(response.status(), Status::Unauthorized); } -} \ No newline at end of file +} diff --git a/api/src/test.rs b/api/src/test.rs index b1db8f9..919c206 100644 --- a/api/src/test.rs +++ b/api/src/test.rs @@ -9,7 +9,6 @@ pub mod tests { services::application_service::ApplicationService, }; use rocket::{ - http::{Cookie, Status}, local::blocking::Client, }; use std::sync::Mutex; @@ -60,65 +59,4 @@ pub mod tests { Mutex::from(Client::tracked(rocket).expect("valid rocket instance")) }) } - - pub fn candidate_login(client: &Client) -> (Cookie, Cookie) { - let response = client - .post("/candidate/login") - .body(format!( - "{{ - \"application_id\": {}, - \"password\": \"{}\" - }}", - APPLICATION_ID, CANDIDATE_PASSWORD - )) - .dispatch(); - - ( - response.cookies().get("id").unwrap().to_owned(), - response.cookies().get("key").unwrap().to_owned(), - ) - } - - pub fn admin_login(client: &Client) -> (Cookie, Cookie) { - let response = client - .post("/admin/login") - .body(format!( - "{{ - \"admin_id\": {}, - \"password\": \"{}\" - }}", - ADMIN_ID, ADMIN_PASSWORD - )) - .dispatch(); - - println!("{:?}", response); - ( - response.cookies().get("id").unwrap().to_owned(), - response.cookies().get("key").unwrap().to_owned(), - ) - } - - pub fn create_candidate( - client: &Client, - cookies: (Cookie, Cookie), - id: i32, - pid: String, - ) -> String { - let response = client - .post("/admin/create") - .body(format!( - "{{ - \"application_id\": {}, - \"personal_id_number\": \"{}\" - }}", - id, pid - )) - .cookie(cookies.0) - .cookie(cookies.1) - .dispatch(); - - assert_eq!(response.status(), Status::Ok); - - response.into_string().unwrap() - } } From 1eb026aa2c04a5cbb4919ec02e87b9f4c87b0350 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Mon, 21 Nov 2022 18:01:42 +0100 Subject: [PATCH 9/9] fix: remove duplicate admin_login function --- api/src/routes/admin.rs | 4 ++-- api/src/routes/candidate.rs | 21 +-------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs index a3d6efc..1e9daaa 100644 --- a/api/src/routes/admin.rs +++ b/api/src/routes/admin.rs @@ -159,12 +159,12 @@ pub async fn get_candidate_portfolio( } #[cfg(test)] -mod tests { +pub mod tests { use rocket::{local::blocking::Client, http::{Cookie, Status}}; use crate::test::tests::{test_client, ADMIN_PASSWORD, ADMIN_ID}; - fn admin_login(client: &Client) -> (Cookie, Cookie) { + pub fn admin_login(client: &Client) -> (Cookie, Cookie) { let response = client .post("/admin/login") .body(format!( diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index e83252a..3309d76 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -289,7 +289,7 @@ mod tests { local::blocking::Client, }; - use crate::test::tests::{test_client, APPLICATION_ID, CANDIDATE_PASSWORD, ADMIN_PASSWORD, ADMIN_ID}; + use crate::{test::tests::{test_client, APPLICATION_ID, CANDIDATE_PASSWORD}, routes::admin::tests::admin_login}; fn candidate_login(client: &Client) -> (Cookie, Cookie) { let response = client @@ -309,25 +309,6 @@ mod tests { ) } - fn admin_login(client: &Client) -> (Cookie, Cookie) { - let response = client - .post("/admin/login") - .body(format!( - "{{ - \"admin_id\": {}, - \"password\": \"{}\" - }}", - ADMIN_ID, ADMIN_PASSWORD - )) - .dispatch(); - - println!("{:?}", response); - ( - response.cookies().get("id").unwrap().to_owned(), - response.cookies().get("key").unwrap().to_owned(), - ) - } - const CANDIDATE_DETAILS: &'static str = "{ \"name\": \"idk\", \"surname\": \"idk\",