fix(users): Allow accepting invites for org_admins (#6253)

This commit is contained in:
Mani Chandra
2024-10-08 16:47:52 +05:30
committed by GitHub
parent 364a2a67d4
commit 2bc21cfc5e
6 changed files with 83 additions and 23 deletions

View File

@ -119,7 +119,7 @@ impl UserRole {
conn: &PgPooledConn,
user_id: String,
org_id: id_type::OrganizationId,
merchant_id: id_type::MerchantId,
merchant_id: Option<id_type::MerchantId>,
profile_id: Option<id_type::ProfileId>,
update: UserRoleUpdate,
version: UserRoleVersion,

View File

@ -647,7 +647,14 @@ async fn handle_existing_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 {
@ -678,7 +685,10 @@ async fn handle_existing_user_invitation(
{
let invitee_email = domain::UserEmail::from_pii_email(request.email.clone())?;
let entity = match role_info.get_entity_type() {
EntityType::Organization => return Err(UserErrors::InvalidRoleId.into()),
EntityType::Organization => email_types::Entity {
entity_id: user_from_token.org_id.get_string_repr().to_owned(),
entity_type: EntityType::Organization,
},
EntityType::Merchant => email_types::Entity {
entity_id: user_from_token.merchant_id.get_string_repr().to_owned(),
entity_type: EntityType::Merchant,
@ -806,7 +816,10 @@ async fn handle_new_user_invitation(
let _ = req_state.clone();
let invitee_email = domain::UserEmail::from_pii_email(request.email.clone())?;
let entity = match role_info.get_entity_type() {
EntityType::Organization => return Err(UserErrors::InvalidRoleId.into()),
EntityType::Organization => email_types::Entity {
entity_id: user_from_token.org_id.get_string_repr().to_owned(),
entity_type: EntityType::Organization,
},
EntityType::Merchant => email_types::Entity {
entity_id: user_from_token.merchant_id.get_string_repr().to_owned(),
entity_type: EntityType::Merchant,
@ -1012,7 +1025,7 @@ pub async fn accept_invite_from_email_token_only_flow(
&state,
user_from_db.get_user_id(),
&org_id,
&merchant_id,
merchant_id.as_ref(),
profile_id.as_ref(),
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,

View File

@ -174,7 +174,7 @@ pub async fn update_user_role(
.update_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
Some(&user_from_token.merchant_id),
user_from_token.profile_id.as_ref(),
UserRoleUpdate::UpdateRole {
role_id: req.role_id.clone(),
@ -247,7 +247,7 @@ pub async fn update_user_role(
.update_user_role_by_user_id_and_lineage(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
Some(&user_from_token.merchant_id),
user_from_token.profile_id.as_ref(),
UserRoleUpdate::UpdateRole {
role_id: req.role_id.clone(),
@ -296,7 +296,7 @@ pub async fn accept_invitations_v2(
&state,
user_from_token.user_id.as_str(),
org_id,
merchant_id,
merchant_id.as_ref(),
profile_id.as_ref(),
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,
@ -348,7 +348,7 @@ pub async fn accept_invitations_pre_auth(
&state,
user_token.user_id.as_str(),
org_id,
merchant_id,
merchant_id.as_ref(),
profile_id.as_ref(),
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,

View File

@ -3043,7 +3043,7 @@ impl UserRoleInterface for KafkaStore {
&self,
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
merchant_id: Option<&id_type::MerchantId>,
profile_id: Option<&id_type::ProfileId>,
update: user_storage::UserRoleUpdate,
version: enums::UserRoleVersion,

View File

@ -52,7 +52,7 @@ pub trait UserRoleInterface {
&self,
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
merchant_id: Option<&id_type::MerchantId>,
profile_id: Option<&id_type::ProfileId>,
update: storage::UserRoleUpdate,
version: enums::UserRoleVersion,
@ -120,7 +120,7 @@ impl UserRoleInterface for Store {
&self,
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
merchant_id: Option<&id_type::MerchantId>,
profile_id: Option<&id_type::ProfileId>,
update: storage::UserRoleUpdate,
version: enums::UserRoleVersion,
@ -130,7 +130,7 @@ impl UserRoleInterface for Store {
&conn,
user_id.to_owned(),
org_id.to_owned(),
merchant_id.to_owned(),
merchant_id.cloned(),
profile_id.cloned(),
update,
version,
@ -280,7 +280,7 @@ impl UserRoleInterface for MockDb {
&self,
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
merchant_id: Option<&id_type::MerchantId>,
profile_id: Option<&id_type::ProfileId>,
update: storage::UserRoleUpdate,
version: enums::UserRoleVersion,
@ -293,11 +293,11 @@ impl UserRoleInterface for MockDb {
&& user_role.profile_id.is_none();
let merchant_level_check = user_role.org_id.as_ref() == Some(org_id)
&& user_role.merchant_id.as_ref() == Some(merchant_id)
&& user_role.merchant_id.as_ref() == merchant_id
&& user_role.profile_id.is_none();
let profile_level_check = user_role.org_id.as_ref() == Some(org_id)
&& user_role.merchant_id.as_ref() == Some(merchant_id)
&& user_role.merchant_id.as_ref() == merchant_id
&& user_role.profile_id.as_ref() == profile_id;
// Check if the user role matches the conditions and the version matches

View File

@ -174,7 +174,7 @@ pub async fn update_v1_and_v2_user_roles_in_db(
state: &SessionState,
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
merchant_id: Option<&id_type::MerchantId>,
profile_id: Option<&id_type::ProfileId>,
update: UserRoleUpdate,
) -> (
@ -255,12 +255,57 @@ pub async fn get_lineage_for_user_id_and_entity_for_accepting_invite(
) -> UserResult<
Option<(
id_type::OrganizationId,
id_type::MerchantId,
Option<id_type::MerchantId>,
Option<id_type::ProfileId>,
)>,
> {
match entity_type {
EntityType::Organization => Err(UserErrors::InvalidRoleOperation.into()),
EntityType::Organization => {
let Ok(org_id) =
id_type::OrganizationId::try_from(std::borrow::Cow::from(entity_id.clone()))
else {
return Ok(None);
};
let user_roles = state
.store
.list_user_roles_by_user_id(ListUserRolesByUserIdPayload {
user_id,
org_id: Some(&org_id),
merchant_id: None,
profile_id: None,
entity_id: None,
version: None,
status: Some(UserStatus::InvitationSent),
limit: None,
})
.await
.change_context(UserErrors::InternalServerError)?
.into_iter()
.collect::<HashSet<_>>();
if user_roles.len() > 1 {
return Ok(None);
}
if let Some(user_role) = user_roles.into_iter().next() {
let (_entity_id, entity_type) = user_role
.get_entity_id_and_type()
.ok_or(UserErrors::InternalServerError)?;
if entity_type != EntityType::Organization {
return Ok(None);
}
return Ok(Some((
user_role.org_id.ok_or(UserErrors::InternalServerError)?,
None,
None,
)));
}
Ok(None)
}
EntityType::Merchant => {
let Ok(merchant_id) = id_type::MerchantId::wrap(entity_id) else {
return Ok(None);
@ -298,7 +343,7 @@ pub async fn get_lineage_for_user_id_and_entity_for_accepting_invite(
return Ok(Some((
user_role.org_id.ok_or(UserErrors::InternalServerError)?,
merchant_id,
Some(merchant_id),
None,
)));
}
@ -343,9 +388,11 @@ pub async fn get_lineage_for_user_id_and_entity_for_accepting_invite(
return Ok(Some((
user_role.org_id.ok_or(UserErrors::InternalServerError)?,
user_role
.merchant_id
.ok_or(UserErrors::InternalServerError)?,
Some(
user_role
.merchant_id
.ok_or(UserErrors::InternalServerError)?,
),
Some(profile_id),
)));
}