Skip to content

Commit

Permalink
feat(users): add global support in user roles (#6458)
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorvdixit88 authored and Sayak Bhattacharya committed Nov 26, 2024
1 parent 60ff8a4 commit b79183f
Show file tree
Hide file tree
Showing 18 changed files with 211 additions and 34 deletions.
2 changes: 2 additions & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,8 @@ diesel::table! {
#[max_length = 64]
entity_type -> Nullable<Varchar>,
version -> UserRoleVersion,
#[max_length = 64]
tenant_id -> Varchar,
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/diesel_models/src/schema_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,8 @@ diesel::table! {
#[max_length = 64]
entity_type -> Nullable<Varchar>,
version -> UserRoleVersion,
#[max_length = 64]
tenant_id -> Varchar,
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/diesel_models/src/user_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct UserRole {
pub entity_id: Option<String>,
pub entity_type: Option<EntityType>,
pub version: enums::UserRoleVersion,
pub tenant_id: String,
}

impl UserRole {
Expand Down Expand Up @@ -87,6 +88,7 @@ pub struct UserRoleNew {
pub entity_id: Option<String>,
pub entity_type: Option<EntityType>,
pub version: enums::UserRoleVersion,
pub tenant_id: String,
}

#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
Expand Down
4 changes: 2 additions & 2 deletions crates/router/src/analytics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1853,7 +1853,7 @@ pub mod routes {
return Err(OpenSearchError::AccessForbiddenError)?;
}
let user_roles: HashSet<UserRole> = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: &auth.user_id,
org_id: Some(&auth.org_id),
Expand Down Expand Up @@ -1976,7 +1976,7 @@ pub mod routes {
return Err(OpenSearchError::AccessForbiddenError)?;
}
let user_roles: HashSet<UserRole> = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: &auth.user_id,
org_id: Some(&auth.org_id),
Expand Down
6 changes: 6 additions & 0 deletions crates/router/src/core/errors/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ pub enum UserErrors {
MaxTotpAttemptsReached,
#[error("Maximum attempts reached for Recovery Code")]
MaxRecoveryCodeAttemptsReached,
#[error("Forbidden tenant id")]
ForbiddenTenantId,
}

impl common_utils::errors::ErrorSwitch<api_models::errors::types::ApiErrorResponse> for UserErrors {
Expand Down Expand Up @@ -239,6 +241,9 @@ impl common_utils::errors::ErrorSwitch<api_models::errors::types::ApiErrorRespon
Self::MaxRecoveryCodeAttemptsReached => {
AER::BadRequest(ApiError::new(sub_code, 49, self.get_error_message(), None))
}
Self::ForbiddenTenantId => {
AER::BadRequest(ApiError::new(sub_code, 50, self.get_error_message(), None))
}
}
}
}
Expand Down Expand Up @@ -289,6 +294,7 @@ impl UserErrors {
Self::AuthConfigParsingError => "Auth config parsing error",
Self::SSOFailed => "Invalid SSO request",
Self::JwtProfileIdMissing => "profile_id missing in JWT",
Self::ForbiddenTenantId => "Forbidden tenant id",
}
}
}
1 change: 1 addition & 0 deletions crates/router/src/core/recon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub async fn generate_recon_token(
&state.conf,
user.org_id.clone(),
user.profile_id.clone(),
user.tenant_id,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
Expand Down
58 changes: 47 additions & 11 deletions crates/router/src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ async fn handle_existing_user_invitation(
let now = common_utils::date_time::now();

if state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
invitee_user_from_db.get_user_id(),
&user_from_token.org_id,
Expand All @@ -614,7 +614,7 @@ async fn handle_existing_user_invitation(
}

if state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
invitee_user_from_db.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -650,6 +650,10 @@ async fn handle_existing_user_invitation(
EntityType::Organization => {
user_role
.add_entity(domain::OrganizationLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
})
.insert_in_v2(state)
Expand All @@ -658,6 +662,10 @@ async fn handle_existing_user_invitation(
EntityType::Merchant => {
user_role
.add_entity(domain::MerchantLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
merchant_id: user_from_token.merchant_id.clone(),
})
Expand All @@ -671,6 +679,10 @@ async fn handle_existing_user_invitation(
.ok_or(UserErrors::InternalServerError)?;
user_role
.add_entity(domain::ProfileLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
merchant_id: user_from_token.merchant_id.clone(),
profile_id: profile_id.clone(),
Expand Down Expand Up @@ -777,6 +789,10 @@ async fn handle_new_user_invitation(
EntityType::Organization => {
user_role
.add_entity(domain::OrganizationLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
})
.insert_in_v2(state)
Expand All @@ -785,6 +801,10 @@ async fn handle_new_user_invitation(
EntityType::Merchant => {
user_role
.add_entity(domain::MerchantLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
merchant_id: user_from_token.merchant_id.clone(),
})
Expand All @@ -798,6 +818,10 @@ async fn handle_new_user_invitation(
.ok_or(UserErrors::InternalServerError)?;
user_role
.add_entity(domain::ProfileLevel {
tenant_id: user_from_token
.tenant_id
.clone()
.unwrap_or(state.tenant.tenant_id.clone()),
org_id: user_from_token.org_id.clone(),
merchant_id: user_from_token.merchant_id.clone(),
profile_id: profile_id.clone(),
Expand Down Expand Up @@ -864,6 +888,7 @@ async fn handle_new_user_invitation(
org_id: user_from_token.org_id.clone(),
role_id: request.role_id.clone(),
profile_id: None,
tenant_id: user_from_token.tenant_id.clone(),
};

let set_metadata_request = SetMetaDataRequest::IsChangePasswordRequired;
Expand Down Expand Up @@ -909,7 +934,7 @@ pub async fn resend_invite(
.into();

let user_role = match state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user.get_user_id(),
&user_from_token.org_id,
Expand All @@ -932,7 +957,7 @@ pub async fn resend_invite(
let user_role = match user_role {
Some(user_role) => user_role,
None => state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -1102,6 +1127,13 @@ pub async fn create_internal_user(
}
})?;

let default_tenant_id = common_utils::consts::DEFAULT_TENANT.to_string();

if state.tenant.tenant_id != default_tenant_id {
return Err(UserErrors::ForbiddenTenantId)
.attach_printable("Operation allowed only for the default tenant.");
}

let internal_merchant_id = common_utils::id_type::MerchantId::get_internal_user_merchant_id(
consts::user_role::INTERNAL_USER_MERCHANT_ID,
);
Expand Down Expand Up @@ -1142,6 +1174,7 @@ pub async fn create_internal_user(
UserStatus::Active,
)
.add_entity(domain::MerchantLevel {
tenant_id: default_tenant_id,
org_id: internal_merchant.organization_id,
merchant_id: internal_merchant_id,
})
Expand Down Expand Up @@ -1195,7 +1228,7 @@ pub async fn list_user_roles_details(
}

let user_roles_set = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: required_user.get_user_id(),
org_id: Some(&user_from_token.org_id),
Expand Down Expand Up @@ -2372,7 +2405,7 @@ pub async fn list_orgs_for_user(
}

let orgs = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: user_from_token.user_id.as_str(),
org_id: None,
Expand Down Expand Up @@ -2437,7 +2470,7 @@ pub async fn list_merchants_for_user_in_org(
.change_context(UserErrors::InternalServerError)?,
EntityType::Merchant | EntityType::Profile => {
let merchant_ids = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: user_from_token.user_id.as_str(),
org_id: Some(&user_from_token.org_id),
Expand Down Expand Up @@ -2516,7 +2549,7 @@ pub async fn list_profiles_for_user_in_org_and_merchant_account(
.change_context(UserErrors::InternalServerError)?,
EntityType::Profile => {
let profile_ids = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: user_from_token.user_id.as_str(),
org_id: Some(&user_from_token.org_id),
Expand Down Expand Up @@ -2592,7 +2625,7 @@ pub async fn switch_org_for_user(
}

let user_role = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: &user_from_token.user_id,
org_id: Some(&request.org_id),
Expand Down Expand Up @@ -2621,6 +2654,7 @@ pub async fn switch_org_for_user(
request.org_id.clone(),
user_role.role_id.clone(),
profile_id.clone(),
user_from_token.tenant_id,
)
.await?;

Expand Down Expand Up @@ -2764,7 +2798,7 @@ pub async fn switch_merchant_for_user_in_org(

EntityType::Merchant | EntityType::Profile => {
let user_role = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: &user_from_token.user_id,
org_id: Some(&user_from_token.org_id),
Expand Down Expand Up @@ -2805,6 +2839,7 @@ pub async fn switch_merchant_for_user_in_org(
org_id.clone(),
role_id.clone(),
profile_id,
user_from_token.tenant_id,
)
.await?;

Expand Down Expand Up @@ -2879,7 +2914,7 @@ pub async fn switch_profile_for_user_in_org_and_merchant(

EntityType::Profile => {
let user_role = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload{
user_id:&user_from_token.user_id,
org_id: Some(&user_from_token.org_id),
Expand Down Expand Up @@ -2910,6 +2945,7 @@ pub async fn switch_profile_for_user_in_org_and_merchant(
user_from_token.org_id.clone(),
role_id.clone(),
profile_id,
user_from_token.tenant_id,
)
.await?;

Expand Down
20 changes: 10 additions & 10 deletions crates/router/src/core/user_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub async fn update_user_role(
let mut is_updated = false;

let v2_user_role_to_be_updated = match state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -210,7 +210,7 @@ pub async fn update_user_role(
}

state
.store
.global_store
.update_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Expand All @@ -229,7 +229,7 @@ pub async fn update_user_role(
}

let v1_user_role_to_be_updated = match state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -283,7 +283,7 @@ pub async fn update_user_role(
}

state
.store
.global_store
.update_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -470,7 +470,7 @@ pub async fn delete_user_role(

// Find in V2
let user_role_v2 = match state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user_from_db.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -517,7 +517,7 @@ pub async fn delete_user_role(

user_role_deleted_flag = true;
state
.store
.global_store
.delete_user_role_by_user_id_and_lineage(
user_from_db.get_user_id(),
&user_from_token.org_id,
Expand All @@ -532,7 +532,7 @@ pub async fn delete_user_role(

// Find in V1
let user_role_v1 = match state
.store
.global_store
.find_user_role_by_user_id_and_lineage(
user_from_db.get_user_id(),
&user_from_token.org_id,
Expand Down Expand Up @@ -579,7 +579,7 @@ pub async fn delete_user_role(

user_role_deleted_flag = true;
state
.store
.global_store
.delete_user_role_by_user_id_and_lineage(
user_from_db.get_user_id(),
&user_from_token.org_id,
Expand All @@ -599,7 +599,7 @@ pub async fn delete_user_role(

// Check if user has any more role associations
let remaining_roles = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: user_from_db.get_user_id(),
org_id: None,
Expand Down Expand Up @@ -780,7 +780,7 @@ pub async fn list_invitations_for_user(
user_from_token: auth::UserIdFromAuth,
) -> UserResponse<Vec<user_role_api::ListInvitationForUserResponse>> {
let user_roles = state
.store
.global_store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id: &user_from_token.user_id,
org_id: None,
Expand Down
Loading

0 comments on commit b79183f

Please sign in to comment.