Skip to content

Commit

Permalink
Made new hashing dependacy from resent commit injectable to fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
williamwoldum committed Nov 27, 2023
1 parent bbbf1df commit b8d59d9
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 24 deletions.
15 changes: 8 additions & 7 deletions src/api/ecdar_api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::api::hashing_context::HashingContextTrait;
use crate::api::server::server::get_auth_token_request::user_credentials;
use crate::entities::access;
use crate::entities::session;
use bcrypt::hash;
use regex::Regex;
use sea_orm::SqlErr;
use std::sync::Arc;
Expand Down Expand Up @@ -38,10 +38,9 @@ pub struct ConcreteEcdarApi {
session_context: Arc<dyn SessionContextTrait>,
user_context: Arc<dyn UserContextTrait>,
reveaal_context: Arc<dyn EcdarBackend>,
hashing_context: Arc<dyn HashingContextTrait>,
}

const HASH_COST: u32 = 12;

/// Updates or creates a session in the database for a given user.
///
///
Expand Down Expand Up @@ -131,6 +130,7 @@ impl ConcreteEcdarApi {
session_context: Arc<dyn SessionContextTrait>,
user_context: Arc<dyn UserContextTrait>,
reveaal_context: Arc<dyn EcdarBackend>,
hashing_context: Arc<dyn HashingContextTrait>,
) -> Self {

Check failure on line 134 in src/api/ecdar_api.rs

View workflow job for this annotation

GitHub Actions / Clippy lint and check

this function has too many arguments (8/7)

error: this function has too many arguments (8/7) --> src/api/ecdar_api.rs:125:5 | 125 | / pub fn new( 126 | | access_context: Arc<dyn AccessContextTrait>, 127 | | in_use_context: Arc<dyn InUseContextTrait>, 128 | | model_context: Arc<dyn ModelContextTrait>, ... | 133 | | hashing_context: Arc<dyn HashingContextTrait>, 134 | | ) -> Self { | |_____________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments = note: `-D clippy::too-many-arguments` implied by `-D clippy::complexity` = help: to override `-D clippy::complexity` add `#[allow(clippy::too_many_arguments)]`

Check failure on line 134 in src/api/ecdar_api.rs

View workflow job for this annotation

GitHub Actions / Clippy lint and check

this function has too many arguments (8/7)

error: this function has too many arguments (8/7) --> src/api/ecdar_api.rs:125:5 | 125 | / pub fn new( 126 | | access_context: Arc<dyn AccessContextTrait>, 127 | | in_use_context: Arc<dyn InUseContextTrait>, 128 | | model_context: Arc<dyn ModelContextTrait>, ... | 133 | | hashing_context: Arc<dyn HashingContextTrait>, 134 | | ) -> Self { | |_____________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments = note: `-D clippy::too-many-arguments` implied by `-D clippy::complexity` = help: to override `-D clippy::complexity` add `#[allow(clippy::too_many_arguments)]`
ConcreteEcdarApi {
access_context,
Expand All @@ -140,6 +140,7 @@ impl ConcreteEcdarApi {
session_context,
user_context,
reveaal_context,
hashing_context,
}
}
}
Expand Down Expand Up @@ -256,7 +257,7 @@ impl EcdarApi for ConcreteEcdarApi {

// Record to be inserted in database
let new_user = user::Model {
id: Default::default(),
id: uid,
username: match message.clone().username {
Some(username) => {
if is_valid_username(username.as_str()) {
Expand All @@ -278,7 +279,7 @@ impl EcdarApi for ConcreteEcdarApi {
None => user.email,
},
password: match message.clone().password {
Some(password) => hash(password, HASH_COST).unwrap(),
Some(password) => self.hashing_context.hash_password(password),
None => user.password,
},
};
Expand Down Expand Up @@ -384,7 +385,7 @@ impl EcdarApi for ConcreteEcdarApi {
async fn get_auth_find_user_helper(
user_context: Arc<dyn UserContextTrait>,
user_credentials: UserCredentials,
) -> Result<UserEntity, Status> {
) -> Result<user::Model, Status> {
if let Some(user) = user_credentials.user {
match user {
user_credentials::User::Username(username) => Ok(user_context
Expand Down Expand Up @@ -485,7 +486,7 @@ impl EcdarApiAuth for ConcreteEcdarApi {
return Err(Status::new(Code::InvalidArgument, "Invalid email"));
}

let user = UserEntity {
let user = user::Model {
id: Default::default(),
username: message.clone().username,
password: message.clone().password,
Expand Down
18 changes: 18 additions & 0 deletions src/api/hashing_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use bcrypt::{hash, verify, DEFAULT_COST};

pub trait HashingContextTrait: Send + Sync {
fn hash_password(&self, password: String) -> String;
fn verify_password(&self, password: String, hash: &str) -> bool;
}

pub struct HashingContext;

impl HashingContextTrait for HashingContext {
fn hash_password(&self, password: String) -> String {
hash(password, DEFAULT_COST).unwrap()
}

fn verify_password(&self, password: String, hash: &str) -> bool {
verify(password, hash).unwrap()
}
}
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod auth;
pub mod ecdar_api;
pub mod hashing_context;
pub mod reveaal_context;
pub mod server;
3 changes: 3 additions & 0 deletions src/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use tonic::transport::Server;

use crate::api::auth;
use crate::api::ecdar_api::ConcreteEcdarApi;
use crate::api::hashing_context::HashingContextTrait;
use crate::api::server::server::ecdar_api_auth_server::EcdarApiAuthServer;
use crate::api::server::server::ecdar_api_server::EcdarApiServer;
use crate::api::server::server::ecdar_backend_server::{EcdarBackend, EcdarBackendServer};
Expand All @@ -27,6 +28,7 @@ pub async fn start_grpc_server(
session_context: Arc<dyn SessionContextTrait>,
user_context: Arc<dyn UserContextTrait>,
reveaal_context: Arc<dyn EcdarBackend>,
hashing_context: Arc<dyn HashingContextTrait>,
) -> Result<(), Box<dyn std::error::Error>> {

Check failure on line 32 in src/api/server.rs

View workflow job for this annotation

GitHub Actions / Clippy lint and check

this function has too many arguments (8/7)

error: this function has too many arguments (8/7) --> src/api/server.rs:23:1 | 23 | / pub async fn start_grpc_server( 24 | | access_context: Arc<dyn AccessContextTrait>, 25 | | in_use_context: Arc<dyn InUseContextTrait>, 26 | | model_context: Arc<dyn ModelContextTrait>, ... | 31 | | hashing_context: Arc<dyn HashingContextTrait>, 32 | | ) -> Result<(), Box<dyn std::error::Error>> { | |___________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments

Check failure on line 32 in src/api/server.rs

View workflow job for this annotation

GitHub Actions / Clippy lint and check

this function has too many arguments (8/7)

error: this function has too many arguments (8/7) --> src/api/server.rs:23:1 | 23 | / pub async fn start_grpc_server( 24 | | access_context: Arc<dyn AccessContextTrait>, 25 | | in_use_context: Arc<dyn InUseContextTrait>, 26 | | model_context: Arc<dyn ModelContextTrait>, ... | 31 | | hashing_context: Arc<dyn HashingContextTrait>, 32 | | ) -> Result<(), Box<dyn std::error::Error>> { | |___________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
// defining address for our service
let addr = env::var("API_ADDRESS")
Expand All @@ -44,6 +46,7 @@ pub async fn start_grpc_server(
session_context,
user_context,
reveaal_context,
hashing_context,
);

// adding services to our server.
Expand Down
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod database;
mod entities;
mod tests;

use crate::api::hashing_context::HashingContext;
use crate::api::reveaal_context::ReveaalContext;
use crate::database::access_context::AccessContext;
use crate::database::database_context::{PostgresDatabaseContext, SQLiteDatabaseContext};
Expand Down Expand Up @@ -39,6 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let session_context = Arc::new(SessionContext::new(db_context.clone()));
let in_use_context = Arc::new(InUseContext::new(db_context.clone()));
let reveaal_context = Arc::new(ReveaalContext);
let hashing_context = Arc::new(HashingContext);

start_grpc_server(
access_context,
Expand All @@ -48,6 +50,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
session_context,
user_context,
reveaal_context,
hashing_context,
)
.await
.unwrap();
Expand Down
12 changes: 12 additions & 0 deletions src/tests/api/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![cfg(test)]

use crate::api::ecdar_api::ConcreteEcdarApi;
use crate::api::hashing_context::HashingContextTrait;
use crate::api::server::server::ecdar_backend_server::EcdarBackend;
use crate::api::server::server::{
QueryRequest, QueryResponse, SimulationStartRequest, SimulationStepRequest,
Expand Down Expand Up @@ -29,6 +30,7 @@ pub fn get_mock_concrete_ecdar_api(mock_services: MockServices) -> ConcreteEcdar
Arc::new(mock_services.session_context_mock),
Arc::new(mock_services.user_context_mock),
Arc::new(mock_services.reveaal_context_mock),
Arc::new(mock_services.hashing_context_mock),
)
}

Expand All @@ -41,6 +43,7 @@ pub fn get_mock_services() -> MockServices {
session_context_mock: MockSessionContext::new(),
user_context_mock: MockUserContext::new(),
reveaal_context_mock: MockReveaalContext::new(),
hashing_context_mock: MockHashingContext::new(),
}
}

Expand All @@ -52,6 +55,7 @@ pub struct MockServices {
pub(crate) session_context_mock: MockSessionContext,
pub(crate) user_context_mock: MockUserContext,
pub(crate) reveaal_context_mock: MockReveaalContext,
pub(crate) hashing_context_mock: MockHashingContext,
}

mock! {
Expand Down Expand Up @@ -153,3 +157,11 @@ mock! {
async fn take_simulation_step(&self, request: Request<SimulationStepRequest>) -> Result<Response<SimulationStepResponse>, Status>;
}
}

mock! {
pub HashingContext {}
impl HashingContextTrait for HashingContext {
fn hash_password(&self, password: String) -> String;
fn verify_password(&self, password: String, hash: &str) -> bool;
}
}
32 changes: 15 additions & 17 deletions src/tests/api/user_logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,21 +214,20 @@ async fn test_create_user_valid_request_returns_ok() {

#[tokio::test]
async fn update_user_returns_ok() {
//todo!(update user implementation should be changed to populate unchanged fields with existing values)
let mut mock_services = get_mock_services();

let old_user = user::Model {
id: 1,
email: "newuser@example.com".to_string(),
email: "olduser@example.com".to_string(),
username: "old_username".to_string(),
password: "StrongPassword123".to_string(),
};

let user = user::Model {
let new_user = user::Model {
id: 1,
email: "[email protected]".to_string(),
username: "new_username".to_string(),
password: "StrongPassword123".to_string(),
password: "g76df2gd7hd837g8hjd8723hd8gd823d82d3".to_string(),
};

mock_services
Expand All @@ -237,11 +236,17 @@ async fn update_user_returns_ok() {
.with(predicate::eq(1))
.returning(move |_| Ok(Some(old_user.clone())));

mock_services
.hashing_context_mock
.expect_hash_password()
.with(predicate::eq("StrongPassword123".to_string()))
.returning(move |_| "g76df2gd7hd837g8hjd8723hd8gd823d82d3".to_string());

mock_services
.user_context_mock
.expect_update()
.with(predicate::eq(user.clone()))
.returning(move |_| Ok(user.clone()));
.with(predicate::eq(new_user.clone()))
.returning(move |_| Ok(new_user.clone()));

let api = get_mock_concrete_ecdar_api(mock_services);

Expand All @@ -264,17 +269,10 @@ async fn update_user_returns_ok() {
async fn update_user_non_existant_user_returns_err() {
let mut mock_services = get_mock_services();

let user = user::Model {
id: 1,
email: "new_test@test".to_string(),
username: "new_test_user".to_string(),
password: "new_test_pass".to_string(),
};

mock_services
.user_context_mock
.expect_update()
.with(predicate::eq(user.clone()))
.expect_get_by_id()
.with(predicate::eq(1))
.returning(move |_| Err(DbErr::RecordNotFound("".to_string())));

let api = get_mock_concrete_ecdar_api(mock_services);
Expand All @@ -289,7 +287,7 @@ async fn update_user_non_existant_user_returns_err() {
.metadata_mut()
.insert("uid", metadata::MetadataValue::from_str("1").unwrap());

let update_user_response = api.update_user(update_user_request).await;
let res = api.update_user(update_user_request).await;

assert!(update_user_response.is_err())
assert_eq!(res.unwrap_err().code(), Code::Internal);
}

0 comments on commit b8d59d9

Please sign in to comment.