From a07e85b104dc48201ec88cd131bc90c215502d26 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 8 Apr 2024 21:58:38 +0200 Subject: [PATCH] test: [#448] category context tests and minor refactoring --- src/services/authorization.rs | 142 +++++++++++++++++++++++++++++++++- src/services/category.rs | 8 -- src/services/user.rs | 3 +- 3 files changed, 142 insertions(+), 11 deletions(-) diff --git a/src/services/authorization.rs b/src/services/authorization.rs index ab42dc1a..b86833d2 100644 --- a/src/services/authorization.rs +++ b/src/services/authorization.rs @@ -47,6 +47,144 @@ impl Service { self.user_repository.get_compact(&user_id).await } } - +#[allow(unused_imports)] #[cfg(test)] -mod tests {} +mod test { + use std::str::FromStr; + use std::sync::Arc; + + use mockall::predicate; + + use crate::databases::database; + use crate::errors::ServiceError; + use crate::models::user::{User, UserCompact}; + use crate::services::authorization::{Service, ACTION}; + use crate::services::user::{MockRepository, Repository}; + use crate::web::api::client::v1::random::string; + + #[tokio::test] + async fn a_guest_user_should_not_be_able_to_add_categories() { + let test_user_id = 1; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(|_| Err(ServiceError::UserNotFound)); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!( + service.authorize(ACTION::AddCategory, Some(test_user_id)).await, + Err(ServiceError::UserNotFound) + ); + } + + #[tokio::test] + async fn a_registered_user_should_not_be_able_to_add_categories() { + let test_user_id = 2; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(move |_| { + Ok(UserCompact { + user_id: test_user_id, + username: "non_admin_user".to_string(), + administrator: false, + }) + }); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!( + service.authorize(ACTION::AddCategory, Some(test_user_id)).await, + Err(ServiceError::Unauthorized) + ); + } + + #[tokio::test] + async fn an_admin_user_should_be_able_to_add_categories() { + let test_user_id = 3; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(move |_| { + Ok(UserCompact { + user_id: test_user_id, + username: "admin_user".to_string(), + administrator: true, + }) + }); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!(service.authorize(ACTION::AddCategory, Some(test_user_id)).await, Ok(())); + } + + #[tokio::test] + async fn a_guest_user_should_not_be_able_to_delete_categories() { + let test_user_id = 4; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(|_| Err(ServiceError::UserNotFound)); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!( + service.authorize(ACTION::DeleteCategory, Some(test_user_id)).await, + Err(ServiceError::UserNotFound) + ); + } + + #[tokio::test] + async fn a_registered_user_should_not_be_able_to_delete_categories() { + let test_user_id = 5; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(move |_| { + Ok(UserCompact { + user_id: test_user_id, + username: "non_admin_user".to_string(), + administrator: false, + }) + }); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!( + service.authorize(ACTION::DeleteCategory, Some(test_user_id)).await, + Err(ServiceError::Unauthorized) + ); + } + + #[tokio::test] + async fn an_admin_user_should_be_able_to_delete_categories() { + let test_user_id = 6; + + let mut mock_repository = MockRepository::new(); + mock_repository + .expect_get_compact() + .with(predicate::eq(test_user_id)) + .times(1) + .returning(move |_| { + Ok(UserCompact { + user_id: test_user_id, + username: "admin_user".to_string(), + administrator: true, + }) + }); + + let service = Service::new(Arc::new(Box::new(mock_repository))); + assert_eq!(service.authorize(ACTION::DeleteCategory, Some(test_user_id)).await, Ok(())); + } +} diff --git a/src/services/category.rs b/src/services/category.rs index e21aded3..0bcaca80 100644 --- a/src/services/category.rs +++ b/src/services/category.rs @@ -39,14 +39,6 @@ impl Service { /// * The category already exists. /// * There is a database error. pub async fn add_category(&self, category_name: &str, user_id: &UserId) -> Result { - /*let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - }*/ - self.authorization_service .authorize(ACTION::AddCategory, Some(*user_id)) .await?; diff --git a/src/services/user.rs b/src/services/user.rs index 3e39fc17..dc397c17 100644 --- a/src/services/user.rs +++ b/src/services/user.rs @@ -6,6 +6,7 @@ use argon2::{Argon2, PasswordHasher}; use async_trait::async_trait; use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; use log::{debug, info}; +#[cfg(test)] use mockall::automock; use pbkdf2::password_hash::rand_core::OsRng; @@ -235,7 +236,7 @@ impl BanService { } } -#[automock] +#[cfg_attr(test, automock)] #[async_trait] pub trait Repository: Sync + Send { async fn get_compact(&self, user_id: &UserId) -> Result;