refactor(users): Make profile_id in the JWT non-optional (#6537)

This commit is contained in:
Mani Chandra
2024-11-18 12:56:00 +05:30
committed by GitHub
parent df32e82500
commit d32397f060
8 changed files with 58 additions and 110 deletions

View File

@ -87,7 +87,7 @@ impl UserRole {
user_id: String,
org_id: id_type::OrganizationId,
merchant_id: id_type::MerchantId,
profile_id: Option<id_type::ProfileId>,
profile_id: id_type::ProfileId,
version: UserRoleVersion,
) -> StorageResult<Self> {
// Checking in user roles, for a user in token hierarchy, only one of the relation will be true, either org level, merchant level or profile level
@ -103,7 +103,6 @@ impl UserRole {
.or(dsl::org_id.eq(org_id).and(
dsl::merchant_id
.eq(merchant_id)
//TODO: In case of None, profile_id = NULL its unexpected behaviour, after V1 profile id will not be option
.and(dsl::profile_id.eq(profile_id)),
));
@ -137,7 +136,6 @@ impl UserRole {
.or(dsl::org_id.eq(org_id).and(
dsl::merchant_id
.eq(merchant_id)
//TODO: In case of None, profile_id = NULL its unexpected behaviour, after V1 profile id will not be option
.and(dsl::profile_id.eq(profile_id)),
));
@ -160,7 +158,7 @@ impl UserRole {
user_id: String,
org_id: id_type::OrganizationId,
merchant_id: id_type::MerchantId,
profile_id: Option<id_type::ProfileId>,
profile_id: id_type::ProfileId,
version: UserRoleVersion,
) -> StorageResult<Self> {
// Checking in user roles, for a user in token hierarchy, only one of the relation will be true, either org level, merchant level or profile level
@ -176,7 +174,6 @@ impl UserRole {
.or(dsl::org_id.eq(org_id).and(
dsl::merchant_id
.eq(merchant_id)
//TODO: In case of None, profile_id = NULL its unexpected behaviour, after V1 profile id will not be option
.and(dsl::profile_id.eq(profile_id)),
));

View File

@ -119,9 +119,7 @@ pub async fn get_user_details(
org_id: user_from_token.org_id,
is_two_factor_auth_setup: user.get_totp_status() == TotpStatus::Set,
recovery_codes_left: user.get_recovery_codes().map(|codes| codes.len()),
profile_id: user_from_token
.profile_id
.ok_or(UserErrors::JwtProfileIdMissing)?,
profile_id: user_from_token.profile_id,
entity_type: role_info.get_entity_type(),
},
))
@ -603,7 +601,7 @@ async fn handle_existing_user_invitation(
invitee_user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V1,
)
.await
@ -619,7 +617,7 @@ async fn handle_existing_user_invitation(
invitee_user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V2,
)
.await
@ -673,10 +671,6 @@ async fn handle_existing_user_invitation(
.await?
}
EntityType::Profile => {
let profile_id = user_from_token
.profile_id
.clone()
.ok_or(UserErrors::InternalServerError)?;
user_role
.add_entity(domain::ProfileLevel {
tenant_id: user_from_token
@ -685,7 +679,7 @@ async fn handle_existing_user_invitation(
.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(),
profile_id: user_from_token.profile_id.clone(),
})
.insert_in_v2(state)
.await?
@ -705,16 +699,10 @@ async fn handle_existing_user_invitation(
entity_id: user_from_token.merchant_id.get_string_repr().to_owned(),
entity_type: EntityType::Merchant,
},
EntityType::Profile => {
let profile_id = user_from_token
.profile_id
.clone()
.ok_or(UserErrors::InternalServerError)?;
email_types::Entity {
entity_id: profile_id.get_string_repr().to_owned(),
entity_type: EntityType::Profile,
}
}
EntityType::Profile => email_types::Entity {
entity_id: user_from_token.profile_id.get_string_repr().to_owned(),
entity_type: EntityType::Profile,
},
};
let email_contents = email_types::InviteUser {
@ -812,10 +800,6 @@ async fn handle_new_user_invitation(
.await?
}
EntityType::Profile => {
let profile_id = user_from_token
.profile_id
.clone()
.ok_or(UserErrors::InternalServerError)?;
user_role
.add_entity(domain::ProfileLevel {
tenant_id: user_from_token
@ -824,7 +808,7 @@ async fn handle_new_user_invitation(
.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(),
profile_id: user_from_token.profile_id.clone(),
})
.insert_in_v2(state)
.await?
@ -848,16 +832,10 @@ async fn handle_new_user_invitation(
entity_id: user_from_token.merchant_id.get_string_repr().to_owned(),
entity_type: EntityType::Merchant,
},
EntityType::Profile => {
let profile_id = user_from_token
.profile_id
.clone()
.ok_or(UserErrors::InternalServerError)?;
email_types::Entity {
entity_id: profile_id.get_string_repr().to_owned(),
entity_type: EntityType::Profile,
}
}
EntityType::Profile => email_types::Entity {
entity_id: user_from_token.profile_id.get_string_repr().to_owned(),
entity_type: EntityType::Profile,
},
};
let email_contents = email_types::InviteUser {
@ -887,7 +865,7 @@ async fn handle_new_user_invitation(
merchant_id: user_from_token.merchant_id.clone(),
org_id: user_from_token.org_id.clone(),
role_id: request.role_id.clone(),
profile_id: None,
profile_id: user_from_token.profile_id.clone(),
tenant_id: user_from_token.tenant_id.clone(),
};
@ -939,7 +917,7 @@ pub async fn resend_invite(
user.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V2,
)
.await
@ -962,7 +940,7 @@ pub async fn resend_invite(
user.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V1,
)
.await
@ -1235,10 +1213,7 @@ pub async fn list_user_roles_details(
merchant_id: (requestor_role_info.get_entity_type() <= EntityType::Merchant)
.then_some(&user_from_token.merchant_id),
profile_id: (requestor_role_info.get_entity_type() <= EntityType::Profile)
.then_some(&user_from_token.profile_id)
.cloned()
.flatten()
.as_ref(),
.then_some(&user_from_token.profile_id),
entity_id: None,
version: None,
status: None,
@ -2865,7 +2840,7 @@ pub async fn switch_profile_for_user_in_org_and_merchant(
request: user_api::SwitchProfileRequest,
user_from_token: auth::UserFromToken,
) -> UserResponse<user_api::TokenResponse> {
if user_from_token.profile_id == Some(request.profile_id.clone()) {
if user_from_token.profile_id == request.profile_id {
return Err(UserErrors::InvalidRoleOperationWithMessage(
"User switching to same profile".to_string(),
)

View File

@ -161,7 +161,7 @@ pub async fn update_user_role(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V2,
)
.await
@ -215,7 +215,7 @@ pub async fn update_user_role(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Some(&user_from_token.merchant_id),
user_from_token.profile_id.as_ref(),
Some(&user_from_token.profile_id),
UserRoleUpdate::UpdateRole {
role_id: req.role_id.clone(),
modified_by: user_from_token.user_id.clone(),
@ -234,7 +234,7 @@ pub async fn update_user_role(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V1,
)
.await
@ -288,7 +288,7 @@ pub async fn update_user_role(
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
Some(&user_from_token.merchant_id),
user_from_token.profile_id.as_ref(),
Some(&user_from_token.profile_id),
UserRoleUpdate::UpdateRole {
role_id: req.role_id.clone(),
modified_by: user_from_token.user_id,
@ -475,7 +475,7 @@ pub async fn delete_user_role(
user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V2,
)
.await
@ -522,7 +522,7 @@ pub async fn delete_user_role(
user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V2,
)
.await
@ -537,7 +537,7 @@ pub async fn delete_user_role(
user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V1,
)
.await
@ -584,7 +584,7 @@ pub async fn delete_user_role(
user_from_db.get_user_id(),
&user_from_token.org_id,
&user_from_token.merchant_id,
user_from_token.profile_id.as_ref(),
&user_from_token.profile_id,
UserRoleVersion::V1,
)
.await
@ -676,17 +676,13 @@ pub async fn list_users_in_lineage(
.await?
}
EntityType::Profile => {
let Some(profile_id) = user_from_token.profile_id.as_ref() else {
return Err(UserErrors::JwtProfileIdMissing.into());
};
utils::user_role::fetch_user_roles_by_payload(
&state,
ListUserRolesByOrgIdPayload {
user_id: None,
org_id: &user_from_token.org_id,
merchant_id: Some(&user_from_token.merchant_id),
profile_id: Some(profile_id),
profile_id: Some(&user_from_token.profile_id),
version: None,
limit: None,
},

View File

@ -3030,7 +3030,7 @@ impl UserRoleInterface for KafkaStore {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
self.diesel_store
@ -3070,7 +3070,7 @@ impl UserRoleInterface for KafkaStore {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
self.diesel_store

View File

@ -45,7 +45,7 @@ pub trait UserRoleInterface {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError>;
@ -64,7 +64,7 @@ pub trait UserRoleInterface {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError>;
@ -100,7 +100,7 @@ impl UserRoleInterface for Store {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
let conn = connection::pg_connection_read(self).await?;
@ -109,7 +109,7 @@ impl UserRoleInterface for Store {
user_id.to_owned(),
org_id.to_owned(),
merchant_id.to_owned(),
profile_id.cloned(),
profile_id.to_owned(),
version,
)
.await
@ -146,7 +146,7 @@ impl UserRoleInterface for Store {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
let conn = connection::pg_connection_write(self).await?;
@ -155,7 +155,7 @@ impl UserRoleInterface for Store {
user_id.to_owned(),
org_id.to_owned(),
merchant_id.to_owned(),
profile_id.cloned(),
profile_id.to_owned(),
version,
)
.await
@ -245,7 +245,7 @@ impl UserRoleInterface for MockDb {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
let user_roles = self.user_roles.lock().await;
@ -261,7 +261,7 @@ impl UserRoleInterface for MockDb {
let profile_level_check = user_role.org_id.as_ref() == Some(org_id)
&& user_role.merchant_id.as_ref() == Some(merchant_id)
&& user_role.profile_id.as_ref() == profile_id;
&& user_role.profile_id.as_ref() == Some(profile_id);
// Check if any condition matches and the version matches
if user_role.user_id == user_id
@ -338,7 +338,7 @@ impl UserRoleInterface for MockDb {
user_id: &str,
org_id: &id_type::OrganizationId,
merchant_id: &id_type::MerchantId,
profile_id: Option<&id_type::ProfileId>,
profile_id: &id_type::ProfileId,
version: enums::UserRoleVersion,
) -> CustomResult<storage::UserRole, errors::StorageError> {
let mut user_roles = self.user_roles.lock().await;
@ -355,7 +355,7 @@ impl UserRoleInterface for MockDb {
let profile_level_check = role.org_id.as_ref() == Some(org_id)
&& role.merchant_id.as_ref() == Some(merchant_id)
&& role.profile_id.as_ref() == profile_id;
&& role.profile_id.as_ref() == Some(profile_id);
// Check if the user role matches the conditions and the version matches
role.user_id == user_id

View File

@ -87,7 +87,7 @@ pub struct AuthenticationDataWithUser {
pub merchant_account: domain::MerchantAccount,
pub key_store: domain::MerchantKeyStore,
pub user: storage::User,
pub profile_id: Option<id_type::ProfileId>,
pub profile_id: id_type::ProfileId,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
@ -231,7 +231,7 @@ pub struct AuthToken {
pub role_id: String,
pub exp: u64,
pub org_id: id_type::OrganizationId,
pub profile_id: Option<id_type::ProfileId>,
pub profile_id: id_type::ProfileId,
pub tenant_id: Option<String>,
}
@ -243,7 +243,7 @@ impl AuthToken {
role_id: String,
settings: &Settings,
org_id: id_type::OrganizationId,
profile_id: Option<id_type::ProfileId>,
profile_id: id_type::ProfileId,
tenant_id: Option<String>,
) -> UserResult<String> {
let exp_duration = std::time::Duration::from_secs(consts::JWT_TOKEN_TIME_IN_SECS);
@ -267,7 +267,7 @@ pub struct UserFromToken {
pub merchant_id: id_type::MerchantId,
pub role_id: String,
pub org_id: id_type::OrganizationId,
pub profile_id: Option<id_type::ProfileId>,
pub profile_id: id_type::ProfileId,
pub tenant_id: Option<String>,
}
@ -1829,7 +1829,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
@ -2077,7 +2077,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
auth.clone(),
@ -2253,11 +2253,7 @@ where
return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
}
if payload
.profile_id
.as_ref()
.is_some_and(|profile_id| *profile_id != self.profile_id)
{
if payload.profile_id != self.profile_id {
return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
}
@ -2290,7 +2286,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
auth.clone(),
@ -2354,30 +2350,14 @@ where
.to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
.attach_printable("Failed to fetch merchant account for the merchant id")?;
if let Some(ref payload_profile_id) = payload.profile_id {
if *payload_profile_id != self.profile_id {
return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
} else {
// if both of them are same then proceed with the profile id present in the request
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: Some(self.profile_id.clone()),
};
Ok((
auth.clone(),
AuthenticationType::MerchantJwt {
merchant_id: auth.merchant_account.get_id().clone(),
user_id: Some(payload.user_id),
},
))
}
if payload.profile_id != self.profile_id {
return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
} else {
// if profile_id is not present in the auth_layer itself then no change in behaviour
// if both of them are same then proceed with the profile id present in the request
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(self.profile_id.clone()),
};
Ok((
auth.clone(),
@ -2527,7 +2507,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
auth,
@ -2663,7 +2643,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
(auth.clone(), payload.user_id.clone()),
@ -2781,7 +2761,7 @@ where
let auth = AuthenticationData {
merchant_account: merchant,
key_store,
profile_id: payload.profile_id,
profile_id: Some(payload.profile_id),
};
Ok((
auth.clone(),

View File

@ -132,7 +132,7 @@ impl JWTFlow {
.clone()
.ok_or(report!(UserErrors::InternalServerError))
.attach_printable("org_id not found")?,
Some(profile_id),
profile_id,
Some(user_role.tenant_id.clone()),
)
.await

View File

@ -100,7 +100,7 @@ pub async fn generate_jwt_auth_token_with_attributes(
role_id,
&state.conf,
org_id,
Some(profile_id),
profile_id,
tenant_id,
)
.await?;