From 12ba0c8dd28eb44566c03441259b19ae144d57f4 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Wed, 22 Jan 2025 20:09:50 +0530 Subject: [PATCH] fix: accept user_id from caller --- src/identity/adapters/input/web/errors.rs | 1 + src/identity/application/services/errors.rs | 1 + src/identity/application/services/mod.rs | 4 +- .../services/register_user/command.rs | 8 +++ .../services/register_user/service.rs | 62 +++++++++++++------ 5 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/identity/adapters/input/web/errors.rs b/src/identity/adapters/input/web/errors.rs index 2fc271d..a71f393 100644 --- a/src/identity/adapters/input/web/errors.rs +++ b/src/identity/adapters/input/web/errors.rs @@ -76,6 +76,7 @@ impl From for WebError { IdentityError::StoreIDNotFound => Self::StoreIDNotFound, IdentityError::DuplicateStoreID => Self::DuplicateStoreID, IdentityError::DuplicateRoleID => Self::DuplicateRoleID, + IdentityError::DuplicateUserID => Self::InternalError, IdentityError::DuplicateRoleName => Self::DuplicateRoleName, IdentityError::RoleIDNotFound => Self::RoleIDNotFound, IdentityError::RoleNotFound => Self::RoleNotFound, diff --git a/src/identity/application/services/errors.rs b/src/identity/application/services/errors.rs index 613cd35..3407464 100644 --- a/src/identity/application/services/errors.rs +++ b/src/identity/application/services/errors.rs @@ -32,6 +32,7 @@ pub enum IdentityError { DuplicateStoreName, StoreIDNotFound, DuplicateStoreID, + DuplicateUserID, DuplicateRoleID, DuplicateRoleName, RoleIDNotFound, diff --git a/src/identity/application/services/mod.rs b/src/identity/application/services/mod.rs index 7d30306..890c597 100644 --- a/src/identity/application/services/mod.rs +++ b/src/identity/application/services/mod.rs @@ -307,7 +307,6 @@ impl IdentityServices { .db_user_id_exists_adapter(out_db_user_id_exists.clone()) .db_create_verification_secret_adapter(out_db_create_verification_secret.clone()) .mailer_account_validation_link_adapter(out_mailer_account_validating_link.clone()) - .get_uuid(get_uuid.clone()) .random_string_adapter(random_string.clone()) .build() .unwrap(), @@ -488,7 +487,8 @@ mod tests { use random_number::tests::mock_generate_random_number; use crate::{ - tests::bdd::IS_NEVER_CALLED, + identity::adapters::output::db::postgres::DBOutPostgresAdapter, + tests::bdd::{IGNORE_CALL_COUNT, IS_NEVER_CALLED}, utils::{random_string::tests::mock_generate_random_string, uuid::tests::mock_get_uuid}, }; diff --git a/src/identity/application/services/register_user/command.rs b/src/identity/application/services/register_user/command.rs index c57e8ae..f68b026 100644 --- a/src/identity/application/services/register_user/command.rs +++ b/src/identity/application/services/register_user/command.rs @@ -6,6 +6,7 @@ use super::*; use derive_builder::Builder; use derive_getters::Getters; use serde::{Deserialize, Serialize}; +use uuid::Uuid; #[derive( Clone, Debug, Serialize, Deserialize, Builder, Eq, PartialEq, Ord, PartialOrd, Getters, @@ -16,6 +17,7 @@ pub struct UnvalidatedRegisterUserCommand { email: String, password: String, confirm_password: String, + user_id: Uuid, } #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters)] @@ -24,6 +26,7 @@ pub struct RegisterUserCommand { last_name: String, email: String, hashed_password: String, + user_id: Uuid, } impl UnvalidatedRegisterUserCommand { @@ -43,6 +46,7 @@ impl UnvalidatedRegisterUserCommand { last_name: self.last_name, email: self.email, hashed_password, + user_id: self.user_id, }) } } @@ -50,6 +54,7 @@ impl UnvalidatedRegisterUserCommand { #[cfg(test)] pub mod tests { use super::*; + use crate::utils::uuid::tests::UUID; pub const PASSWORD: &str = "sadfasdfasdf"; @@ -61,6 +66,7 @@ pub mod tests { let email = "john@example.com"; UnvalidatedRegisterUserCommandBuilder::default() + .user_id(UUID) .first_name(first_name.into()) .last_name(last_name.into()) .email(email.into()) @@ -83,6 +89,7 @@ pub mod tests { let wrong_password = "sadfasdfasdf--wrong"; UnvalidatedRegisterUserCommandBuilder::default() + .user_id(UUID) .first_name(first_name.into()) .last_name(last_name.into()) .email(email.into()) @@ -95,6 +102,7 @@ pub mod tests { assert_eq!( UnvalidatedRegisterUserCommandBuilder::default() + .user_id(UUID) .first_name(first_name.into()) .last_name(last_name.into()) .email(first_name.into()) diff --git a/src/identity/application/services/register_user/service.rs b/src/identity/application/services/register_user/service.rs index 1e20bc2..e015da7 100644 --- a/src/identity/application/services/register_user/service.rs +++ b/src/identity/application/services/register_user/service.rs @@ -15,13 +15,12 @@ use crate::utils::{random_string::*, uuid::*}; pub const SECRET_LEN: usize = 20; pub const REGISTRATION_SECRET_PURPOSE: &str = "account_validation"; -#[derive(Builder)] +#[derive(Builder, Clone)] pub struct RegisterUserService { db_email_exists_adapter: EmailExistsOutDBPortObj, db_user_id_exists_adapter: UserIDExistsOutDBPortObj, db_create_verification_secret_adapter: CreateVerificationSecretOutDBPortObj, mailer_account_validation_link_adapter: AccountValidationLinkOutMailerPortObj, - get_uuid: GetUUIDInterfaceObj, random_string_adapter: GenerateRandomStringInterfaceObj, } @@ -40,18 +39,13 @@ impl RegisterUserUseCase for RegisterUserService { return Err(IdentityError::DuplicateEmail); } - let mut user_id = self.get_uuid.get_uuid(); - loop { - if self - .db_user_id_exists_adapter - .user_id_exists(&user_id) - .await - .unwrap() - { - user_id = self.get_uuid.get_uuid(); - } else { - break; - } + if self + .db_user_id_exists_adapter + .user_id_exists(cmd.user_id()) + .await + .unwrap() + { + return Err(IdentityError::DuplicateUserID); } let secret = self.random_string_adapter.get_random(SECRET_LEN); @@ -60,7 +54,7 @@ impl RegisterUserUseCase for RegisterUserService { .create_verification_secret( CreateSecretMsgBuilder::default() .secret(secret.clone()) - .user_id(user_id) + .user_id(*cmd.user_id()) .build() .unwrap(), ) @@ -75,7 +69,7 @@ impl RegisterUserUseCase for RegisterUserService { Ok(events::UserRegisteredEventBuilder::default() .first_name(cmd.first_name().into()) .last_name(cmd.last_name().into()) - .user_id(user_id) + .user_id(*cmd.user_id()) .email(cmd.email().into()) .hashed_password(cmd.hashed_password().into()) .is_verified(false) @@ -137,7 +131,6 @@ mod tests { .mailer_account_validation_link_adapter(mock_account_validation_link_mailer_port( IS_CALLED_ONLY_ONCE, )) - .get_uuid(mock_get_uuid(IS_CALLED_ONLY_ONCE)) .build() .unwrap(); @@ -157,7 +150,7 @@ mod tests { let s = RegisterUserServiceBuilder::default() .db_user_id_exists_adapter(mock_user_id_exists_db_port( - IGNORE_CALL_COUNT, + IS_CALLED_ONLY_ONCE, RETURNS_FALSE, )) .db_create_verification_secret_adapter(mock_create_verification_secret_db_port( @@ -171,7 +164,6 @@ mod tests { .mailer_account_validation_link_adapter(mock_account_validation_link_mailer_port( IS_NEVER_CALLED, )) - .get_uuid(mock_get_uuid(IS_NEVER_CALLED)) .build() .unwrap(); @@ -180,4 +172,36 @@ mod tests { Some(IdentityError::DuplicateEmail) ); } + + #[actix_rt::test] + async fn test_register_user_service_user_id_exists() { + let cmd = command::RegisterUserCommand::get_command(); + + let s = RegisterUserServiceBuilder::default() + .db_user_id_exists_adapter(mock_user_id_exists_db_port( + IS_CALLED_ONLY_ONCE, + RETURNS_TRUE, + )) + .db_create_verification_secret_adapter(mock_create_verification_secret_db_port( + IS_NEVER_CALLED, + )) + .db_email_exists_adapter(mock_email_exists_db_port( + IS_CALLED_ONLY_ONCE, + RETURNS_FALSE, + )) + .random_string_adapter(mock_generate_random_string( + IS_NEVER_CALLED, + RETURNS_RANDOM_STRING.into(), + )) + .mailer_account_validation_link_adapter(mock_account_validation_link_mailer_port( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + assert_eq!( + s.register_user(cmd.clone()).await.err(), + Some(IdentityError::DuplicateUserID) + ); + } }