diff --git a/crates/api_models/src/user_role.rs b/crates/api_models/src/user_role.rs index 72fca2b2f08..b057f8ca8bc 100644 --- a/crates/api_models/src/user_role.rs +++ b/crates/api_models/src/user_role.rs @@ -43,6 +43,7 @@ pub enum Permission { SurchargeDecisionManagerRead, UsersRead, UsersWrite, + MerchantAccountCreate, } #[derive(Debug, serde::Serialize)] @@ -60,6 +61,7 @@ pub enum PermissionModule { Files, ThreeDsDecisionManager, SurchargeDecisionManager, + AccountCreate, } #[derive(Debug, serde::Serialize)] diff --git a/crates/router/src/core/user_role.rs b/crates/router/src/core/user_role.rs index 2b7752d1904..d8ff836e1f8 100644 --- a/crates/router/src/core/user_role.rs +++ b/crates/router/src/core/user_role.rs @@ -20,7 +20,7 @@ pub async fn get_authorization_info( user_role_api::AuthorizationInfoResponse( info::get_authorization_info() .into_iter() - .filter_map(|module| module.try_into().ok()) + .map(Into::into) .collect(), ), )) @@ -63,6 +63,22 @@ pub async fn get_role( Ok(ApplicationResponse::Json(info)) } +pub async fn get_role_from_token( + _state: AppState, + user: auth::UserFromToken, +) -> UserResponse> { + Ok(ApplicationResponse::Json( + predefined_permissions::PREDEFINED_PERMISSIONS + .get(user.role_id.as_str()) + .ok_or(UserErrors::InternalServerError.into()) + .attach_printable("Invalid Role Id in JWT")? + .get_permissions() + .iter() + .map(|&per| per.into()) + .collect(), + )) +} + pub async fn update_user_role( state: AppState, user_from_token: auth::UserFromToken, diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 0c489dbe63a..34a3b5db51b 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -919,6 +919,7 @@ impl User { .service(web::resource("/permission_info").route(web::get().to(get_authorization_info))) .service(web::resource("/user/update_role").route(web::post().to(update_user_role))) .service(web::resource("/role/list").route(web::get().to(list_roles))) + .service(web::resource("/role").route(web::get().to(get_role_from_token))) .service(web::resource("/role/{role_id}").route(web::get().to(get_role))) .service(web::resource("/user/invite").route(web::post().to(invite_user))) .service( diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 12cf76be475..4dffcb1d38d 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -180,9 +180,11 @@ impl From for ApiIdentifier { | Flow::VerifyEmail | Flow::VerifyEmailRequest => Self::User, - Flow::ListRoles | Flow::GetRole | Flow::UpdateUserRole | Flow::GetAuthorizationInfo => { - Self::UserRole - } + Flow::ListRoles + | Flow::GetRole + | Flow::GetRoleFromToken + | Flow::UpdateUserRole + | Flow::GetAuthorizationInfo => Self::UserRole, Flow::GetActionUrl | Flow::SyncOnboardingStatus | Flow::ResetTrackingId => { Self::ConnectorOnboarding diff --git a/crates/router/src/routes/user_role.rs b/crates/router/src/routes/user_role.rs index c96e099ab16..fe305942d03 100644 --- a/crates/router/src/routes/user_role.rs +++ b/crates/router/src/routes/user_role.rs @@ -7,7 +7,7 @@ use crate::{ core::{api_locking, user_role as user_role_core}, services::{ api, - authentication::{self as auth}, + authentication::{self as auth, UserFromToken}, authorization::permissions::Permission, }, }; @@ -64,6 +64,20 @@ pub async fn get_role( .await } +pub async fn get_role_from_token(state: web::Data, req: HttpRequest) -> HttpResponse { + let flow = Flow::GetRoleFromToken; + Box::pin(api::server_wrap( + flow, + state.clone(), + &req, + (), + |state, user: UserFromToken, _| user_role_core::get_role_from_token(state, user), + &auth::DashboardNoPermissionAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} + pub async fn update_user_role( state: web::Data, req: HttpRequest, diff --git a/crates/router/src/services/authorization/info.rs b/crates/router/src/services/authorization/info.rs index cef93f82739..99e4f1b6c09 100644 --- a/crates/router/src/services/authorization/info.rs +++ b/crates/router/src/services/authorization/info.rs @@ -15,16 +15,13 @@ pub struct PermissionInfo { impl PermissionInfo { pub fn new(permissions: &[Permission]) -> Vec { - let mut permission_infos = Vec::with_capacity(permissions.len()); - for permission in permissions { - if let Some(description) = Permission::get_permission_description(permission) { - permission_infos.push(Self { - enum_name: permission.clone(), - description, - }) - } - } - permission_infos + permissions + .iter() + .map(|&per| Self { + description: Permission::get_permission_description(&per), + enum_name: per, + }) + .collect() } } @@ -43,6 +40,7 @@ pub enum PermissionModule { Files, ThreeDsDecisionManager, SurchargeDecisionManager, + AccountCreate, } impl PermissionModule { @@ -60,7 +58,8 @@ impl PermissionModule { Self::Disputes => "Everything related to disputes - like creating and viewing dispute related information are within this module", Self::Files => "Permissions for uploading, deleting and viewing files for disputes", Self::ThreeDsDecisionManager => "View and configure 3DS decision rules configured for a merchant", - Self::SurchargeDecisionManager =>"View and configure surcharge decision rules configured for a merchant" + Self::SurchargeDecisionManager =>"View and configure surcharge decision rules configured for a merchant", + Self::AccountCreate => "Create new account within your organization" } } } @@ -173,6 +172,11 @@ impl ModuleInfo { Permission::SurchargeDecisionManagerRead, ]), }, + PermissionModule::AccountCreate => Self { + module: module_name, + description, + permissions: PermissionInfo::new(&[Permission::MerchantAccountCreate]), + }, } } } diff --git a/crates/router/src/services/authorization/permissions.rs b/crates/router/src/services/authorization/permissions.rs index 426b048e88b..5c5e3ecce30 100644 --- a/crates/router/src/services/authorization/permissions.rs +++ b/crates/router/src/services/authorization/permissions.rs @@ -1,6 +1,6 @@ use strum::Display; -#[derive(PartialEq, Display, Clone, Debug)] +#[derive(PartialEq, Display, Clone, Debug, Copy)] pub enum Permission { PaymentRead, PaymentWrite, @@ -34,45 +34,43 @@ pub enum Permission { } impl Permission { - pub fn get_permission_description(&self) -> Option<&'static str> { + pub fn get_permission_description(&self) -> &'static str { match self { - Self::PaymentRead => Some("View all payments"), - Self::PaymentWrite => Some("Create payment, download payments data"), - Self::RefundRead => Some("View all refunds"), - Self::RefundWrite => Some("Create refund, download refunds data"), - Self::ApiKeyRead => Some("View API keys (masked generated for the system"), - Self::ApiKeyWrite => Some("Create and update API keys"), - Self::MerchantAccountRead => Some("View merchant account details"), + Self::PaymentRead => "View all payments", + Self::PaymentWrite => "Create payment, download payments data", + Self::RefundRead => "View all refunds", + Self::RefundWrite => "Create refund, download refunds data", + Self::ApiKeyRead => "View API keys (masked generated for the system", + Self::ApiKeyWrite => "Create and update API keys", + Self::MerchantAccountRead => "View merchant account details", Self::MerchantAccountWrite => { - Some("Update merchant account details, configure webhooks, manage api keys") + "Update merchant account details, configure webhooks, manage api keys" } - Self::MerchantConnectorAccountRead => Some("View connectors configured"), + Self::MerchantConnectorAccountRead => "View connectors configured", Self::MerchantConnectorAccountWrite => { - Some("Create, update, verify and delete connector configurations") + "Create, update, verify and delete connector configurations" } - Self::ForexRead => Some("Query Forex data"), - Self::RoutingRead => Some("View routing configuration"), - Self::RoutingWrite => Some("Create and activate routing configurations"), - Self::DisputeRead => Some("View disputes"), - Self::DisputeWrite => Some("Create and update disputes"), - Self::MandateRead => Some("View mandates"), - Self::MandateWrite => Some("Create and update mandates"), - Self::CustomerRead => Some("View customers"), - Self::CustomerWrite => Some("Create, update and delete customers"), - Self::FileRead => Some("View files"), - Self::FileWrite => Some("Create, update and delete files"), - Self::Analytics => Some("Access to analytics module"), - Self::ThreeDsDecisionManagerWrite => Some("Create and update 3DS decision rules"), + Self::ForexRead => "Query Forex data", + Self::RoutingRead => "View routing configuration", + Self::RoutingWrite => "Create and activate routing configurations", + Self::DisputeRead => "View disputes", + Self::DisputeWrite => "Create and update disputes", + Self::MandateRead => "View mandates", + Self::MandateWrite => "Create and update mandates", + Self::CustomerRead => "View customers", + Self::CustomerWrite => "Create, update and delete customers", + Self::FileRead => "View files", + Self::FileWrite => "Create, update and delete files", + Self::Analytics => "Access to analytics module", + Self::ThreeDsDecisionManagerWrite => "Create and update 3DS decision rules", Self::ThreeDsDecisionManagerRead => { - Some("View all 3DS decision rules configured for a merchant") + "View all 3DS decision rules configured for a merchant" } - Self::SurchargeDecisionManagerWrite => { - Some("Create and update the surcharge decision rules") - } - Self::SurchargeDecisionManagerRead => Some("View all the surcharge decision rules"), - Self::UsersRead => Some("View all the users for a merchant"), - Self::UsersWrite => Some("Invite users, assign and update roles"), - Self::MerchantAccountCreate => None, + Self::SurchargeDecisionManagerWrite => "Create and update the surcharge decision rules", + Self::SurchargeDecisionManagerRead => "View all the surcharge decision rules", + Self::UsersRead => "View all the users for a merchant", + Self::UsersWrite => "Invite users, assign and update roles", + Self::MerchantAccountCreate => "Create merchant account", } } } diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs index d271ed5e29d..53c88f8aea1 100644 --- a/crates/router/src/types/domain/user.rs +++ b/crates/router/src/types/domain/user.rs @@ -762,19 +762,13 @@ impl UserFromStorage { } } -impl TryFrom for user_role_api::ModuleInfo { - type Error = (); - fn try_from(value: info::ModuleInfo) -> Result { - let mut permissions = Vec::with_capacity(value.permissions.len()); - for permission in value.permissions { - let permission = permission.try_into()?; - permissions.push(permission); - } - Ok(Self { +impl From for user_role_api::ModuleInfo { + fn from(value: info::ModuleInfo) -> Self { + Self { module: value.module.into(), description: value.description, - permissions, - }) + permissions: value.permissions.into_iter().map(Into::into).collect(), + } } } @@ -794,18 +788,17 @@ impl From for user_role_api::PermissionModule { info::PermissionModule::Files => Self::Files, info::PermissionModule::ThreeDsDecisionManager => Self::ThreeDsDecisionManager, info::PermissionModule::SurchargeDecisionManager => Self::SurchargeDecisionManager, + info::PermissionModule::AccountCreate => Self::AccountCreate, } } } -impl TryFrom for user_role_api::PermissionInfo { - type Error = (); - fn try_from(value: info::PermissionInfo) -> Result { - let enum_name = (&value.enum_name).try_into()?; - Ok(Self { - enum_name, +impl From for user_role_api::PermissionInfo { + fn from(value: info::PermissionInfo) -> Self { + Self { + enum_name: value.enum_name.into(), description: value.description, - }) + } } } diff --git a/crates/router/src/utils/user_role.rs b/crates/router/src/utils/user_role.rs index c474a82981b..65ead92ad34 100644 --- a/crates/router/src/utils/user_role.rs +++ b/crates/router/src/utils/user_role.rs @@ -1,7 +1,6 @@ use api_models::user_role as user_role_api; use diesel_models::enums::UserStatus; use error_stack::ResultExt; -use router_env::logger; use crate::{ consts, @@ -44,52 +43,50 @@ pub fn validate_role_id(role_id: &str) -> UserResult<()> { pub fn get_role_name_and_permission_response( role_info: &RoleInfo, ) -> Option<(Vec, &'static str)> { - role_info - .get_permissions() - .iter() - .map(TryInto::try_into) - .collect::, _>>() - .ok() - .zip(role_info.get_name()) + role_info.get_name().map(|name| { + ( + role_info + .get_permissions() + .iter() + .map(|&per| per.into()) + .collect::>(), + name, + ) + }) } -impl TryFrom<&Permission> for user_role_api::Permission { - type Error = (); - fn try_from(value: &Permission) -> Result { +impl From for user_role_api::Permission { + fn from(value: Permission) -> Self { match value { - Permission::PaymentRead => Ok(Self::PaymentRead), - Permission::PaymentWrite => Ok(Self::PaymentWrite), - Permission::RefundRead => Ok(Self::RefundRead), - Permission::RefundWrite => Ok(Self::RefundWrite), - Permission::ApiKeyRead => Ok(Self::ApiKeyRead), - Permission::ApiKeyWrite => Ok(Self::ApiKeyWrite), - Permission::MerchantAccountRead => Ok(Self::MerchantAccountRead), - Permission::MerchantAccountWrite => Ok(Self::MerchantAccountWrite), - Permission::MerchantConnectorAccountRead => Ok(Self::MerchantConnectorAccountRead), - Permission::MerchantConnectorAccountWrite => Ok(Self::MerchantConnectorAccountWrite), - Permission::ForexRead => Ok(Self::ForexRead), - Permission::RoutingRead => Ok(Self::RoutingRead), - Permission::RoutingWrite => Ok(Self::RoutingWrite), - Permission::DisputeRead => Ok(Self::DisputeRead), - Permission::DisputeWrite => Ok(Self::DisputeWrite), - Permission::MandateRead => Ok(Self::MandateRead), - Permission::MandateWrite => Ok(Self::MandateWrite), - Permission::CustomerRead => Ok(Self::CustomerRead), - Permission::CustomerWrite => Ok(Self::CustomerWrite), - Permission::FileRead => Ok(Self::FileRead), - Permission::FileWrite => Ok(Self::FileWrite), - Permission::Analytics => Ok(Self::Analytics), - Permission::ThreeDsDecisionManagerWrite => Ok(Self::ThreeDsDecisionManagerWrite), - Permission::ThreeDsDecisionManagerRead => Ok(Self::ThreeDsDecisionManagerRead), - Permission::SurchargeDecisionManagerWrite => Ok(Self::SurchargeDecisionManagerWrite), - Permission::SurchargeDecisionManagerRead => Ok(Self::SurchargeDecisionManagerRead), - Permission::UsersRead => Ok(Self::UsersRead), - Permission::UsersWrite => Ok(Self::UsersWrite), - - Permission::MerchantAccountCreate => { - logger::error!("Invalid use of internal permission"); - Err(()) - } + 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::ForexRead => Self::ForexRead, + 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::FileRead => Self::FileRead, + Permission::FileWrite => Self::FileWrite, + 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, } } } diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs index 0d6636e567d..d48aa5f95fe 100644 --- a/crates/router_env/src/logger/types.rs +++ b/crates/router_env/src/logger/types.rs @@ -297,6 +297,8 @@ pub enum Flow { ListRoles, /// Get role GetRole, + /// Get role from token + GetRoleFromToken, /// Update user role UpdateUserRole, /// Create merchant account for user in a org