feat: get roles for store service

This commit is contained in:
Aravinth Manivannan 2025-01-22 18:05:03 +05:30
parent b9536fd15d
commit b31d3cff75
Signed by: realaravinth
GPG key ID: F8F50389936984FF
6 changed files with 183 additions and 18 deletions

View file

@ -52,6 +52,7 @@ pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web::
Arc::new(db.clone()), Arc::new(db.clone()),
Arc::new(db.clone()), Arc::new(db.clone()),
Arc::new(db.clone()), Arc::new(db.clone()),
Arc::new(db.clone()),
Arc::new(mailer.clone()), Arc::new(mailer.clone()),
Arc::new(phone.clone()), Arc::new(phone.clone()),
Arc::new(phone.clone()), Arc::new(phone.clone()),

View file

@ -48,10 +48,10 @@ pub mod tests {
if let Some(times) = times { if let Some(times) = times {
m.expect_get_roles_for_store() m.expect_get_roles_for_store()
.times(times) .times(times)
.return_const(Ok(vec![Role::default()])); .return_const(Ok(vec![Role::get_role()]));
} else { } else {
m.expect_get_roles_for_store() m.expect_get_roles_for_store()
.return_const(Ok(vec![Role::default()])); .return_const(Ok(vec![Role::get_role()]));
} }
Arc::new(m) Arc::new(m)

View file

@ -0,0 +1,121 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use std::sync::Arc;
use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use super::errors::*;
use crate::identity::{
application::port::output::db::{get_roles_for_store::*, store_id_exists::*},
domain::{role_aggregate::*, store_aggregate::*},
};
#[automock]
#[async_trait::async_trait]
pub trait GetRolesForStoreUseCase: Send + Sync {
async fn get_roles_for_store(&self, store: &Store) -> IdentityResult<Vec<Role>>;
}
pub type GetRolesForStoreServiceObj = Arc<dyn GetRolesForStoreUseCase>;
#[derive(Clone, Builder)]
pub struct GetRolesForStoreService {
db_store_id_exists: StoreIDExistsDBPortObj,
db_get_roles_for_store: GetRolesForStoreDBPortObj,
}
#[async_trait::async_trait]
impl GetRolesForStoreUseCase for GetRolesForStoreService {
async fn get_roles_for_store(&self, store: &Store) -> IdentityResult<Vec<Role>> {
if !self
.db_store_id_exists
.store_id_exists(store.store_id())
.await?
{
return Err(IdentityError::StoreNotFound);
}
Ok(self
.db_get_roles_for_store
.get_roles_for_store(*store.store_id())
.await?)
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use crate::tests::bdd::*;
use crate::utils::uuid::tests::*;
pub fn mock_get_roles_for_store_service(
times: Option<usize>,
store: &Store,
) -> GetRolesForStoreServiceObj {
let mut m = MockGetRolesForStoreUseCase::new();
let res = vec![Role::default()];
if let Some(times) = times {
m.expect_get_roles_for_store()
.times(times)
.return_const(Ok(res));
} else {
m.expect_get_roles_for_store().return_const(Ok(res));
}
Arc::new(m)
}
#[actix_rt::test]
// with mock that returns Vec<Role>.len() = 1
async fn test_service() {
let store = Store::default();
let s = GetRolesForStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.db_get_roles_for_store(mock_get_roles_for_store_db_port(IS_CALLED_ONLY_ONCE))
.build()
.unwrap();
let roles = s.get_roles_for_store(&store).await.unwrap();
assert_eq!(roles.len(), 1);
assert_eq!(roles.first().unwrap().to_owned(), Role::get_role());
}
#[actix_rt::test]
// with mock that returns empty Vec<Role>
async fn test_service_empty_res() {
let store = Store::default();
{
let s = GetRolesForStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.db_get_roles_for_store(mock_get_roles_for_store_db_port_empty(IS_CALLED_ONLY_ONCE))
.build()
.unwrap();
let roles = s.get_roles_for_store(&store).await.unwrap();
assert!(roles.is_empty());
}
}
#[actix_rt::test]
async fn test_service_store_id_no_exist() {
let store = Store::default();
let s = GetRolesForStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
.db_get_roles_for_store(mock_get_roles_for_store_db_port_empty(IS_NEVER_CALLED))
.build()
.unwrap();
assert_eq!(
s.get_roles_for_store(&store).await.err(),
Some(IdentityError::StoreNotFound)
);
}
}

View file

@ -32,6 +32,7 @@ pub mod update_password;
//pub mod owner_remove_employee_from_role_service; //pub mod owner_remove_employee_from_role_service;
pub mod add_store_service; pub mod add_store_service;
pub mod get_roles_for_store_service;
pub mod update_store_service; pub mod update_store_service;
use add_store_service::*; use add_store_service::*;
@ -80,6 +81,7 @@ use crate::utils::{
uuid::*, uuid::*,
}; };
use delete_user::command::*; use delete_user::command::*;
use get_roles_for_store_service::*;
use login::command::*; use login::command::*;
use mark_user_verified::command::*; use mark_user_verified::command::*;
use owner_manage_store_employee_service::*; use owner_manage_store_employee_service::*;
@ -94,9 +96,9 @@ use crate::identity::application::port::output::{
create_login_otp::*, create_verification_otp::*, create_verification_secret::*, create_login_otp::*, create_verification_otp::*, create_verification_secret::*,
delete_login_otp::*, delete_verification_otp::*, delete_verification_secret::*, delete_login_otp::*, delete_verification_otp::*, delete_verification_secret::*,
email_exists::*, emp_id_exists::*, get_emp_id_from_phone_number::*, get_login_otp::*, email_exists::*, emp_id_exists::*, get_emp_id_from_phone_number::*, get_login_otp::*,
get_verification_otp::*, get_verification_secret::*, phone_exists::*, role_id_exists::*, get_roles_for_store::*, get_verification_otp::*, get_verification_secret::*,
role_name_exists_for_store::*, store_id_exists::*, store_name_exists::*, user_id_exists::*, phone_exists::*, role_id_exists::*, role_name_exists_for_store::*, store_id_exists::*,
verification_secret_exists::*, store_name_exists::*, user_id_exists::*, verification_secret_exists::*,
}, },
mailer::account_validation_link::*, mailer::account_validation_link::*,
phone::{account_login_otp::*, account_validation_otp::*}, phone::{account_login_otp::*, account_validation_otp::*},
@ -145,6 +147,7 @@ pub trait IdentityServicesInterface: Send + Sync {
fn update_password(&self) -> UpdatePasswordServiceObj; fn update_password(&self) -> UpdatePasswordServiceObj;
fn owner_manage_employee(&self) -> OwnerManageStoreEmployeesServiceObj; fn owner_manage_employee(&self) -> OwnerManageStoreEmployeesServiceObj;
fn add_role_to_store(&self) -> AddRoleToStoreServiceObj; fn add_role_to_store(&self) -> AddRoleToStoreServiceObj;
fn get_roles_for_store(&self) -> GetRolesForStoreServiceObj;
// employee // employee
// fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj; // fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj;
@ -174,6 +177,7 @@ pub struct IdentityServices {
update_password: UpdatePasswordServiceObj, update_password: UpdatePasswordServiceObj,
owner_manage_store_employee: OwnerManageStoreEmployeesServiceObj, owner_manage_store_employee: OwnerManageStoreEmployeesServiceObj,
add_role_to_store: AddRoleToStoreServiceObj, add_role_to_store: AddRoleToStoreServiceObj,
get_roles_for_store: GetRolesForStoreServiceObj,
// employee_accept_invite_service: EmployeeAcceptInviteServiceObj, // employee_accept_invite_service: EmployeeAcceptInviteServiceObj,
employee_exit_organization_service: EmployeeExitOrganizationServiceObj, employee_exit_organization_service: EmployeeExitOrganizationServiceObj,
@ -220,6 +224,9 @@ impl IdentityServicesInterface for IdentityServices {
fn add_role_to_store(&self) -> AddRoleToStoreServiceObj { fn add_role_to_store(&self) -> AddRoleToStoreServiceObj {
self.add_role_to_store.clone() self.add_role_to_store.clone()
} }
fn get_roles_for_store(&self) -> GetRolesForStoreServiceObj {
self.get_roles_for_store.clone()
}
// employee // employee
// fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj { // fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj {
@ -273,6 +280,7 @@ impl IdentityServices {
out_db_verification_secret_exists: VerificationSecretExistsOutDBPortObj, out_db_verification_secret_exists: VerificationSecretExistsOutDBPortObj,
out_db_role_id_exists: RoleIDExistsDBPortObj, out_db_role_id_exists: RoleIDExistsDBPortObj,
out_db_role_name_exists_for_store: RoleNameExistsForStoreDBPortObj, out_db_role_name_exists_for_store: RoleNameExistsForStoreDBPortObj,
out_db_get_roles_for_store: GetRolesForStoreDBPortObj,
out_mailer_account_validating_link: AccountValidationLinkOutMailerPortObj, out_mailer_account_validating_link: AccountValidationLinkOutMailerPortObj,
@ -347,6 +355,14 @@ impl IdentityServices {
.unwrap(), .unwrap(),
); );
let get_roles_for_store: GetRolesForStoreServiceObj = Arc::new(
GetRolesForStoreServiceBuilder::default()
.db_store_id_exists(out_db_store_id_exists.clone())
.db_get_roles_for_store(out_db_get_roles_for_store.clone())
.build()
.unwrap(),
);
// let employee_accept_invite_service: EmployeeAcceptInviteServiceObj = Arc::new( // let employee_accept_invite_service: EmployeeAcceptInviteServiceObj = Arc::new(
// EmployeeAcceptInviteServiceBuilder::default() // EmployeeAcceptInviteServiceBuilder::default()
// .db_get_invite_adapter(unimplemented!()) // .db_get_invite_adapter(unimplemented!())
@ -451,6 +467,7 @@ impl IdentityServices {
update_password, update_password,
owner_manage_store_employee, owner_manage_store_employee,
add_role_to_store, add_role_to_store,
get_roles_for_store,
// employee_accept_invite_service, // employee_accept_invite_service,
employee_exit_organization_service, employee_exit_organization_service,
@ -499,6 +516,7 @@ mod tests {
mock_verification_secret_exists_db_port(IS_NEVER_CALLED, false), mock_verification_secret_exists_db_port(IS_NEVER_CALLED, false),
mock_role_id_exists_db_port_true(IS_NEVER_CALLED), mock_role_id_exists_db_port_true(IS_NEVER_CALLED),
mock_role_name_exists_for_store_db_port_true(IS_NEVER_CALLED), mock_role_name_exists_for_store_db_port_true(IS_NEVER_CALLED),
mock_get_roles_for_store_db_port(IS_NEVER_CALLED),
mock_account_validation_link_mailer_port(IS_NEVER_CALLED), mock_account_validation_link_mailer_port(IS_NEVER_CALLED),
mock_account_validation_otp_phone_port(IS_NEVER_CALLED), mock_account_validation_otp_phone_port(IS_NEVER_CALLED),
mock_account_login_otp_phone_port(IS_NEVER_CALLED), mock_account_login_otp_phone_port(IS_NEVER_CALLED),

View file

@ -235,13 +235,26 @@ mod tests {
use super::*; use super::*;
use crate::identity::{ use crate::identity::{
application::services::{ application::services::{
add_role_to_store_service::AddRoleToStoreService, delete_user::{command::DeleteUserCommand, service::DeleteUserService}, events::IdentityEvent, login::{command::LoginCommand, events::LoginEvent, service::LoginService}, owner_manage_store_employee_service::*, register_user::{ add_role_to_store_service::AddRoleToStoreService,
delete_user::{command::DeleteUserCommand, service::DeleteUserService},
events::IdentityEvent,
login::{command::LoginCommand, events::LoginEvent, service::LoginService},
owner_manage_store_employee_service::*,
register_user::{
command::RegisterUserCommand, events::UserRegisteredEvent, command::RegisterUserCommand, events::UserRegisteredEvent,
service::RegisterUserService, service::RegisterUserService,
}, IdentityCommand, MockIdentityServicesInterface },
IdentityCommand, MockIdentityServicesInterface,
}, },
domain::{ domain::{
add_role_command::AddRoleCommand, employee_removed_from_role::EmployeeRemovedFromRoleEvent, owner_add_employee_to_store_command::*, owner_added_employee_to_store_event::*, owner_remove_employee_from_store_command::OwnerRemoveEmployeeFromStoreCommand, owner_removed_employee_from_store_event::OwnerRemovedEmployeeFromStoreEvent, remove_employee_from_role_command::RemoveEmployeeFromRoleCommand, role_added_event::RoleAddedEvent, role_set_to_employee_event::RoleSetToEmployeeEvent, set_role_to_employee_command::SetRoleToEmployeeCommand add_role_command::AddRoleCommand,
employee_removed_from_role::EmployeeRemovedFromRoleEvent,
owner_add_employee_to_store_command::*, owner_added_employee_to_store_event::*,
owner_remove_employee_from_store_command::OwnerRemoveEmployeeFromStoreCommand,
owner_removed_employee_from_store_event::OwnerRemovedEmployeeFromStoreEvent,
remove_employee_from_role_command::RemoveEmployeeFromRoleCommand,
role_added_event::RoleAddedEvent, role_set_to_employee_event::RoleSetToEmployeeEvent,
set_role_to_employee_command::SetRoleToEmployeeCommand,
}, },
}; };
use crate::tests::bdd::*; use crate::tests::bdd::*;
@ -531,12 +544,10 @@ mod tests {
services services
.expect_add_role_to_store() .expect_add_role_to_store()
.times(IS_CALLED_ONLY_ONCE.unwrap()) .times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const( .return_const(AddRoleToStoreService::mock_service(
AddRoleToStoreService::mock_service(
IS_CALLED_ONLY_ONCE, IS_CALLED_ONLY_ONCE,
cmd.clone(), cmd.clone(),
), ));
);
UserTestFramework::with(Arc::new(services)) UserTestFramework::with(Arc::new(services))
.given_no_previous_events() .given_no_previous_events()

View file

@ -80,10 +80,13 @@ mod tests {
use cqrs_es::test::TestFramework; use cqrs_es::test::TestFramework;
use crate::identity::domain::{ use crate::{
identity::domain::{
add_role_command::*, add_role_command::*,
// accept_invite_command::AcceptInviteCommand, // accept_invite_command::AcceptInviteCommand,
role_added_event::*, role_added_event::*,
},
utils::uuid::tests::UUID,
}; };
use add_role_to_store_service::*; use add_role_to_store_service::*;
@ -92,6 +95,17 @@ mod tests {
type RoleTestFramework = TestFramework<Role>; type RoleTestFramework = TestFramework<Role>;
impl Role {
pub fn get_role() -> Self {
Role {
name: "test_role_should_never_exist_in_prod".to_string(),
store_id: UUID,
role_id: UUID,
deleted: false,
}
}
}
#[test] #[test]
fn test_role_aggregate_add_role() { fn test_role_aggregate_add_role() {
let cmd = AddRoleCommand::get_cmd(); let cmd = AddRoleCommand::get_cmd();