mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
142 lines
5.1 KiB
Rust
142 lines
5.1 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use api_models::user_role as user_role_api;
|
|
use common_enums::PermissionGroup;
|
|
use diesel_models::user_role::UserRole;
|
|
use error_stack::{IntoReport, ResultExt};
|
|
use router_env::logger;
|
|
|
|
use crate::{
|
|
consts,
|
|
core::errors::{UserErrors, UserResult},
|
|
routes::AppState,
|
|
services::authorization::{self as authz, permissions::Permission, roles},
|
|
types::domain,
|
|
};
|
|
|
|
impl From<Permission> for user_role_api::Permission {
|
|
fn from(value: Permission) -> Self {
|
|
match value {
|
|
Permission::PaymentRead => Self::PaymentRead,
|
|
Permission::PaymentWrite => Self::PaymentWrite,
|
|
Permission::RefundRead => Self::RefundRead,
|
|
Permission::RefundWrite => Self::RefundWrite,
|
|
Permission::ApiKeyRead => Self::ApiKeyRead,
|
|
Permission::ApiKeyWrite => Self::ApiKeyWrite,
|
|
Permission::MerchantAccountRead => Self::MerchantAccountRead,
|
|
Permission::MerchantAccountWrite => Self::MerchantAccountWrite,
|
|
Permission::MerchantConnectorAccountRead => Self::MerchantConnectorAccountRead,
|
|
Permission::MerchantConnectorAccountWrite => Self::MerchantConnectorAccountWrite,
|
|
Permission::RoutingRead => Self::RoutingRead,
|
|
Permission::RoutingWrite => Self::RoutingWrite,
|
|
Permission::DisputeRead => Self::DisputeRead,
|
|
Permission::DisputeWrite => Self::DisputeWrite,
|
|
Permission::MandateRead => Self::MandateRead,
|
|
Permission::MandateWrite => Self::MandateWrite,
|
|
Permission::CustomerRead => Self::CustomerRead,
|
|
Permission::CustomerWrite => Self::CustomerWrite,
|
|
Permission::Analytics => Self::Analytics,
|
|
Permission::ThreeDsDecisionManagerWrite => Self::ThreeDsDecisionManagerWrite,
|
|
Permission::ThreeDsDecisionManagerRead => Self::ThreeDsDecisionManagerRead,
|
|
Permission::SurchargeDecisionManagerWrite => Self::SurchargeDecisionManagerWrite,
|
|
Permission::SurchargeDecisionManagerRead => Self::SurchargeDecisionManagerRead,
|
|
Permission::UsersRead => Self::UsersRead,
|
|
Permission::UsersWrite => Self::UsersWrite,
|
|
Permission::MerchantAccountCreate => Self::MerchantAccountCreate,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn validate_role_groups(groups: &[PermissionGroup]) -> UserResult<()> {
|
|
if groups.is_empty() {
|
|
return Err(UserErrors::InvalidRoleOperation.into())
|
|
.attach_printable("Role groups cannot be empty");
|
|
}
|
|
|
|
let unique_groups: HashSet<_> = groups.iter().cloned().collect();
|
|
|
|
if unique_groups.contains(&PermissionGroup::OrganizationManage) {
|
|
return Err(UserErrors::InvalidRoleOperation.into())
|
|
.attach_printable("Organization manage group cannot be added to role");
|
|
}
|
|
|
|
if unique_groups.len() != groups.len() {
|
|
return Err(UserErrors::InvalidRoleOperation.into())
|
|
.attach_printable("Duplicate permission group found");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn validate_role_name(
|
|
state: &AppState,
|
|
role_name: &domain::RoleName,
|
|
merchant_id: &str,
|
|
org_id: &str,
|
|
) -> UserResult<()> {
|
|
let role_name_str = role_name.clone().get_role_name();
|
|
|
|
let is_present_in_predefined_roles = roles::predefined_roles::PREDEFINED_ROLES
|
|
.iter()
|
|
.any(|(_, role_info)| role_info.get_role_name() == role_name_str);
|
|
|
|
// TODO: Create and use find_by_role_name to make this efficient
|
|
let is_present_in_custom_roles = state
|
|
.store
|
|
.list_all_roles(merchant_id, org_id)
|
|
.await
|
|
.change_context(UserErrors::InternalServerError)?
|
|
.iter()
|
|
.any(|role| role.role_name == role_name_str);
|
|
|
|
if is_present_in_predefined_roles || is_present_in_custom_roles {
|
|
return Err(UserErrors::RoleNameAlreadyExists.into());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn set_role_permissions_in_cache_by_user_role(
|
|
state: &AppState,
|
|
user_role: &UserRole,
|
|
) -> bool {
|
|
set_role_permissions_in_cache_if_required(
|
|
state,
|
|
user_role.role_id.as_str(),
|
|
user_role.merchant_id.as_str(),
|
|
user_role.org_id.as_str(),
|
|
)
|
|
.await
|
|
.map_err(|e| logger::error!("Error setting permissions in cache {:?}", e))
|
|
.is_ok()
|
|
}
|
|
|
|
pub async fn set_role_permissions_in_cache_if_required(
|
|
state: &AppState,
|
|
role_id: &str,
|
|
merchant_id: &str,
|
|
org_id: &str,
|
|
) -> UserResult<()> {
|
|
if roles::predefined_roles::PREDEFINED_ROLES.contains_key(role_id) {
|
|
return Ok(());
|
|
}
|
|
|
|
let role_info = roles::RoleInfo::from_role_id(state, role_id, merchant_id, org_id)
|
|
.await
|
|
.change_context(UserErrors::InternalServerError)
|
|
.attach_printable("Error getting role_info from role_id")?;
|
|
|
|
authz::set_permissions_in_cache(
|
|
state,
|
|
role_id,
|
|
&role_info.get_permissions_set().into_iter().collect(),
|
|
consts::JWT_TOKEN_TIME_IN_SECS
|
|
.try_into()
|
|
.into_report()
|
|
.change_context(UserErrors::InternalServerError)?,
|
|
)
|
|
.await
|
|
.change_context(UserErrors::InternalServerError)
|
|
.attach_printable("Error setting permissions in redis")
|
|
}
|