diff --git a/crates/diesel_models/src/query/user_role.rs b/crates/diesel_models/src/query/user_role.rs index 1cd25e54cb..f4142842e2 100644 --- a/crates/diesel_models/src/query/user_role.rs +++ b/crates/diesel_models/src/query/user_role.rs @@ -5,7 +5,6 @@ use diesel::{ BoolExpressionMethods, ExpressionMethods, QueryDsl, }; use error_stack::{report, ResultExt}; -use router_env::logger; use crate::{ enums::{UserRoleVersion, UserStatus}, @@ -23,21 +22,6 @@ impl UserRoleNew { } impl UserRole { - pub async fn insert_multiple_user_roles( - conn: &PgPooledConn, - user_roles: Vec, - ) -> StorageResult> { - let query = diesel::insert_into(::table()).values(user_roles); - - logger::debug!(query = %debug_query::(&query).to_string()); - - query - .get_results_async(conn) - .await - .change_context(errors::DatabaseError::Others) - .attach_printable("Error while inserting user_roles") - } - pub async fn find_by_user_id( conn: &PgPooledConn, user_id: String, diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 9f865c1071..91c86a7405 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -67,7 +67,6 @@ pub async fn signup_with_merchant_id( state.clone(), common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(), UserStatus::Active, - None, ) .await?; @@ -146,7 +145,6 @@ pub async fn signup_token_only_flow( state.clone(), common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(), UserStatus::Active, - None, ) .await?; @@ -247,7 +245,6 @@ pub async fn connect_account( state.clone(), common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(), UserStatus::Active, - None, ) .await?; @@ -657,7 +654,7 @@ async fn handle_existing_user_invitation( org_id: user_from_token.org_id.clone(), merchant_id: user_from_token.merchant_id.clone(), }) - .insert_in_v1_and_v2(state) + .insert_in_v2(state) .await? } EntityType::Profile => { @@ -767,14 +764,21 @@ async fn handle_new_user_invitation( }; let _user_role = match role_info.get_entity_type() { - EntityType::Organization => return Err(UserErrors::InvalidRoleId.into()), + EntityType::Organization => { + user_role + .add_entity(domain::OrganizationLevel { + org_id: user_from_token.org_id.clone(), + }) + .insert_in_v2(state) + .await? + } EntityType::Merchant => { user_role .add_entity(domain::MerchantLevel { org_id: user_from_token.org_id.clone(), merchant_id: user_from_token.merchant_id.clone(), }) - .insert_in_v1_and_v2(state) + .insert_in_v2(state) .await? } EntityType::Profile => { @@ -1128,7 +1132,7 @@ pub async fn create_internal_user( org_id: internal_merchant.organization_id, merchant_id: internal_merchant_id, }) - .insert_in_v1_and_v2(&state) + .insert_in_v2(&state) .await .change_context(UserErrors::InternalServerError)?; @@ -1142,28 +1146,11 @@ pub async fn create_merchant_account( ) -> UserResponse<()> { let user_from_db = user_from_token.get_user_from_db(&state).await?; - let new_user = domain::NewUser::try_from((user_from_db, req, user_from_token))?; - let new_merchant = new_user.get_new_merchant(); + let new_merchant = domain::NewUserMerchant::try_from((user_from_db, req, user_from_token))?; new_merchant .create_new_merchant_and_insert_in_db(state.to_owned()) .await?; - let role_insertion_res = new_user - .insert_org_level_user_role_in_db( - state.clone(), - common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(), - UserStatus::Active, - Some(UserRoleVersion::V1), - ) - .await; - if let Err(e) = role_insertion_res { - let _ = state - .store - .delete_merchant_account_by_merchant_id(&new_merchant.get_merchant_id()) - .await; - return Err(e); - } - Ok(ApplicationResponse::StatusOk) } diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index f0eb5b76fb..33f93ecc69 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -37,10 +37,7 @@ use super::{ user::{sample_data::BatchSampleDataInterface, UserInterface}, user_authentication_method::UserAuthenticationMethodInterface, user_key_store::UserKeyStoreInterface, - user_role::{ - InsertUserRolePayload, ListUserRolesByOrgIdPayload, ListUserRolesByUserIdPayload, - UserRoleInterface, - }, + user_role::{ListUserRolesByOrgIdPayload, ListUserRolesByUserIdPayload, UserRoleInterface}, }; #[cfg(feature = "payouts")] use crate::services::kafka::payout::KafkaPayout; @@ -3018,8 +3015,8 @@ impl RedisConnInterface for KafkaStore { impl UserRoleInterface for KafkaStore { async fn insert_user_role( &self, - user_role: InsertUserRolePayload, - ) -> CustomResult, errors::StorageError> { + user_role: storage::UserRoleNew, + ) -> CustomResult { self.diesel_store.insert_user_role(user_role).await } diff --git a/crates/router/src/db/user_role.rs b/crates/router/src/db/user_role.rs index 9a5c7149b6..d8ef488193 100644 --- a/crates/router/src/db/user_role.rs +++ b/crates/router/src/db/user_role.rs @@ -13,21 +13,6 @@ use crate::{ services::Store, }; -pub enum InsertUserRolePayload { - OnlyV1(storage::UserRoleNew), - OnlyV2(storage::UserRoleNew), - V1AndV2(Box<[storage::UserRoleNew; 2]>), -} - -impl InsertUserRolePayload { - fn convert_to_vec(self) -> Vec { - match self { - Self::OnlyV1(user_role) | Self::OnlyV2(user_role) => vec![user_role], - Self::V1AndV2(user_roles) => user_roles.to_vec(), - } - } -} - pub struct ListUserRolesByOrgIdPayload<'a> { pub user_id: Option<&'a String>, pub org_id: &'a id_type::OrganizationId, @@ -51,8 +36,8 @@ pub struct ListUserRolesByUserIdPayload<'a> { pub trait UserRoleInterface { async fn insert_user_role( &self, - user_role: InsertUserRolePayload, - ) -> CustomResult, errors::StorageError>; + user_role: storage::UserRoleNew, + ) -> CustomResult; async fn find_user_role_by_user_id_and_lineage( &self, @@ -98,11 +83,12 @@ impl UserRoleInterface for Store { #[instrument(skip_all)] async fn insert_user_role( &self, - user_role: InsertUserRolePayload, - ) -> CustomResult, errors::StorageError> { + user_role: storage::UserRoleNew, + ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - storage::UserRole::insert_multiple_user_roles(&conn, user_role.convert_to_vec()) + user_role + .insert(&conn) .await .map_err(|error| report!(errors::StorageError::from(error))) } @@ -217,44 +203,38 @@ impl UserRoleInterface for Store { impl UserRoleInterface for MockDb { async fn insert_user_role( &self, - user_role: InsertUserRolePayload, - ) -> CustomResult, errors::StorageError> { + user_role: storage::UserRoleNew, + ) -> CustomResult { let mut db_user_roles = self.user_roles.lock().await; - user_role - .convert_to_vec() - .into_iter() - .map(|user_role| { - if db_user_roles - .iter() - .any(|user_role_inner| user_role_inner.user_id == user_role.user_id) - { - Err(errors::StorageError::DuplicateValue { - entity: "user_id", - key: None, - })? - } - let user_role = storage::UserRole { - id: i32::try_from(db_user_roles.len()) - .change_context(errors::StorageError::MockDbError)?, - user_id: user_role.user_id, - merchant_id: user_role.merchant_id, - role_id: user_role.role_id, - status: user_role.status, - created_by: user_role.created_by, - created_at: user_role.created_at, - last_modified: user_role.last_modified, - last_modified_by: user_role.last_modified_by, - org_id: user_role.org_id, - profile_id: None, - entity_id: None, - entity_type: None, - version: enums::UserRoleVersion::V1, - }; - db_user_roles.push(user_role.clone()); - Ok(user_role) - }) - .collect::, _>>() + if db_user_roles + .iter() + .any(|user_role_inner| user_role_inner.user_id == user_role.user_id) + { + Err(errors::StorageError::DuplicateValue { + entity: "user_id", + key: None, + })? + } + let user_role = storage::UserRole { + id: i32::try_from(db_user_roles.len()) + .change_context(errors::StorageError::MockDbError)?, + user_id: user_role.user_id, + merchant_id: user_role.merchant_id, + role_id: user_role.role_id, + status: user_role.status, + created_by: user_role.created_by, + created_at: user_role.created_at, + last_modified: user_role.last_modified, + last_modified_by: user_role.last_modified_by, + org_id: user_role.org_id, + profile_id: None, + entity_id: None, + entity_type: None, + version: enums::UserRoleVersion::V1, + }; + db_user_roles.push(user_role.clone()); + Ok(user_role) } async fn find_user_role_by_user_id_and_lineage( diff --git a/crates/router/src/services/authorization/roles/predefined_roles.rs b/crates/router/src/services/authorization/roles/predefined_roles.rs index b271abd1ef..33a1d5f53c 100644 --- a/crates/router/src/services/authorization/roles/predefined_roles.rs +++ b/crates/router/src/services/authorization/roles/predefined_roles.rs @@ -83,9 +83,9 @@ pub static PREDEFINED_ROLES: Lazy> = Lazy::new(| role_name: "organization_admin".to_string(), scope: RoleScope::Organization, entity_type: EntityType::Organization, - is_invitable: false, - is_deletable: false, - is_updatable: false, + is_invitable: true, + is_deletable: true, + is_updatable: true, is_internal: false, }, ); diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs index 6361b82afb..8331dff95c 100644 --- a/crates/router/src/types/domain/user.rs +++ b/crates/router/src/types/domain/user.rs @@ -30,7 +30,7 @@ use crate::{ admin, errors::{UserErrors, UserResult}, }, - db::{user_role::InsertUserRolePayload, GlobalStorageInterface}, + db::GlobalStorageInterface, routes::SessionState, services::{self, authentication::UserFromToken}, types::transformers::ForeignFrom, @@ -661,26 +661,17 @@ impl NewUser { state: SessionState, role_id: String, user_status: UserStatus, - version: Option, ) -> UserResult { let org_id = self .get_new_merchant() .get_new_organization() .get_organization_id(); - let merchant_id = self.get_new_merchant().get_merchant_id(); let org_user_role = self .get_no_level_user_role(role_id, user_status) - .add_entity(OrganizationLevel { - org_id, - merchant_id, - }); + .add_entity(OrganizationLevel { org_id }); - match version { - Some(UserRoleVersion::V1) => org_user_role.insert_in_v1(&state).await, - Some(UserRoleVersion::V2) => org_user_role.insert_in_v2(&state).await, - None => org_user_role.insert_in_v1_and_v2(&state).await, - } + org_user_role.insert_in_v2(&state).await } } @@ -1088,8 +1079,6 @@ pub struct NoLevel; #[derive(Clone)] pub struct OrganizationLevel { pub org_id: id_type::OrganizationId, - // Keeping this to allow insertion of org_admins in V1 - pub merchant_id: id_type::MerchantId, } #[derive(Clone)] @@ -1143,32 +1132,46 @@ pub struct EntityInfo { entity_type: EntityType, } -impl NewUserRole -where - E: Clone, -{ - fn convert_to_new_v1_role( - self, - org_id: id_type::OrganizationId, - merchant_id: id_type::MerchantId, - ) -> UserRoleNew { - UserRoleNew { - user_id: self.user_id, - role_id: self.role_id, - status: self.status, - created_by: self.created_by, - last_modified_by: self.last_modified_by, - created_at: self.created_at, - last_modified: self.last_modified, - org_id: Some(org_id), - merchant_id: Some(merchant_id), +impl From for EntityInfo { + fn from(value: OrganizationLevel) -> Self { + Self { + entity_id: value.org_id.get_string_repr().to_owned(), + entity_type: EntityType::Organization, + org_id: value.org_id, + merchant_id: None, profile_id: None, - entity_id: None, - entity_type: None, - version: UserRoleVersion::V1, } } +} +impl From for EntityInfo { + fn from(value: MerchantLevel) -> Self { + Self { + entity_id: value.merchant_id.get_string_repr().to_owned(), + entity_type: EntityType::Merchant, + org_id: value.org_id, + profile_id: None, + merchant_id: Some(value.merchant_id), + } + } +} + +impl From for EntityInfo { + fn from(value: ProfileLevel) -> Self { + Self { + entity_id: value.profile_id.get_string_repr().to_owned(), + entity_type: EntityType::Profile, + org_id: value.org_id, + merchant_id: Some(value.merchant_id), + profile_id: Some(value.profile_id), + } + } +} + +impl NewUserRole +where + E: Clone + Into, +{ fn convert_to_new_v2_role(self, entity: EntityInfo) -> UserRoleNew { UserRoleNew { user_id: self.user_id, @@ -1187,116 +1190,15 @@ where } } - async fn insert_v1_and_v2_in_db_and_get_v2( - state: &SessionState, - v1_role: UserRoleNew, - v2_role: UserRoleNew, - ) -> UserResult { - let inserted_roles = state - .store - .insert_user_role(InsertUserRolePayload::V1AndV2(Box::new([v1_role, v2_role]))) - .await - .change_context(UserErrors::InternalServerError)?; - - inserted_roles - .into_iter() - .find(|role| role.version == UserRoleVersion::V2) - .ok_or(report!(UserErrors::InternalServerError)) - } -} - -impl NewUserRole { - pub async fn insert_in_v1(self, state: &SessionState) -> UserResult { - let entity = self.entity.clone(); - - let new_v1_role = self - .clone() - .convert_to_new_v1_role(entity.org_id.clone(), entity.merchant_id.clone()); - - state - .store - .insert_user_role(InsertUserRolePayload::OnlyV1(new_v1_role)) - .await - .change_context(UserErrors::InternalServerError)? - .pop() - .ok_or(report!(UserErrors::InternalServerError)) - } - pub async fn insert_in_v2(self, state: &SessionState) -> UserResult { let entity = self.entity.clone(); - let new_v2_role = self.convert_to_new_v2_role(EntityInfo { - org_id: entity.org_id.clone(), - merchant_id: None, - profile_id: None, - entity_id: entity.org_id.get_string_repr().to_owned(), - entity_type: EntityType::Organization, - }); + let new_v2_role = self.convert_to_new_v2_role(entity.into()); + state .store - .insert_user_role(InsertUserRolePayload::OnlyV2(new_v2_role)) + .insert_user_role(new_v2_role) .await - .change_context(UserErrors::InternalServerError)? - .pop() - .ok_or(report!(UserErrors::InternalServerError)) - } - - pub async fn insert_in_v1_and_v2(self, state: &SessionState) -> UserResult { - let entity = self.entity.clone(); - - let new_v1_role = self - .clone() - .convert_to_new_v1_role(entity.org_id.clone(), entity.merchant_id.clone()); - - let new_v2_role = self.clone().convert_to_new_v2_role(EntityInfo { - org_id: entity.org_id.clone(), - merchant_id: None, - profile_id: None, - entity_id: entity.org_id.get_string_repr().to_owned(), - entity_type: EntityType::Organization, - }); - - Self::insert_v1_and_v2_in_db_and_get_v2(state, new_v1_role, new_v2_role).await - } -} - -impl NewUserRole { - pub async fn insert_in_v1_and_v2(self, state: &SessionState) -> UserResult { - let entity = self.entity.clone(); - - let new_v1_role = self - .clone() - .convert_to_new_v1_role(entity.org_id.clone(), entity.merchant_id.clone()); - - let new_v2_role = self.clone().convert_to_new_v2_role(EntityInfo { - org_id: entity.org_id.clone(), - merchant_id: Some(entity.merchant_id.clone()), - profile_id: None, - entity_id: entity.merchant_id.get_string_repr().to_owned(), - entity_type: EntityType::Merchant, - }); - - Self::insert_v1_and_v2_in_db_and_get_v2(state, new_v1_role, new_v2_role).await - } -} - -impl NewUserRole { - pub async fn insert_in_v2(self, state: &SessionState) -> UserResult { - let entity = self.entity.clone(); - - let new_v2_role = self.convert_to_new_v2_role(EntityInfo { - org_id: entity.org_id.clone(), - merchant_id: Some(entity.merchant_id.clone()), - profile_id: Some(entity.profile_id.clone()), - entity_id: entity.profile_id.get_string_repr().to_owned(), - entity_type: EntityType::Profile, - }); - state - .store - .insert_user_role(InsertUserRolePayload::OnlyV2(new_v2_role)) - .await - .change_context(UserErrors::InternalServerError)? - .pop() - .ok_or(report!(UserErrors::InternalServerError)) + .change_context(UserErrors::InternalServerError) } }