feat(users): Added get role from jwt api (#3385)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Rachit Naithani
2024-01-18 20:18:44 +05:30
committed by GitHub
parent 862a1b5303
commit 7516a16763
10 changed files with 140 additions and 111 deletions

View File

@ -43,6 +43,7 @@ pub enum Permission {
SurchargeDecisionManagerRead, SurchargeDecisionManagerRead,
UsersRead, UsersRead,
UsersWrite, UsersWrite,
MerchantAccountCreate,
} }
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]
@ -60,6 +61,7 @@ pub enum PermissionModule {
Files, Files,
ThreeDsDecisionManager, ThreeDsDecisionManager,
SurchargeDecisionManager, SurchargeDecisionManager,
AccountCreate,
} }
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]

View File

@ -20,7 +20,7 @@ pub async fn get_authorization_info(
user_role_api::AuthorizationInfoResponse( user_role_api::AuthorizationInfoResponse(
info::get_authorization_info() info::get_authorization_info()
.into_iter() .into_iter()
.filter_map(|module| module.try_into().ok()) .map(Into::into)
.collect(), .collect(),
), ),
)) ))
@ -63,6 +63,22 @@ pub async fn get_role(
Ok(ApplicationResponse::Json(info)) Ok(ApplicationResponse::Json(info))
} }
pub async fn get_role_from_token(
_state: AppState,
user: auth::UserFromToken,
) -> UserResponse<Vec<user_role_api::Permission>> {
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( pub async fn update_user_role(
state: AppState, state: AppState,
user_from_token: auth::UserFromToken, user_from_token: auth::UserFromToken,

View File

@ -919,6 +919,7 @@ impl User {
.service(web::resource("/permission_info").route(web::get().to(get_authorization_info))) .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("/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/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("/role/{role_id}").route(web::get().to(get_role)))
.service(web::resource("/user/invite").route(web::post().to(invite_user))) .service(web::resource("/user/invite").route(web::post().to(invite_user)))
.service(web::resource("/update").route(web::post().to(update_user_account_details))) .service(web::resource("/update").route(web::post().to(update_user_account_details)))

View File

@ -181,9 +181,11 @@ impl From<Flow> for ApiIdentifier {
| Flow::VerifyEmailRequest | Flow::VerifyEmailRequest
| Flow::UpdateUserAccountDetails => Self::User, | Flow::UpdateUserAccountDetails => Self::User,
Flow::ListRoles | Flow::GetRole | Flow::UpdateUserRole | Flow::GetAuthorizationInfo => { Flow::ListRoles
Self::UserRole | Flow::GetRole
} | Flow::GetRoleFromToken
| Flow::UpdateUserRole
| Flow::GetAuthorizationInfo => Self::UserRole,
Flow::GetActionUrl | Flow::SyncOnboardingStatus | Flow::ResetTrackingId => { Flow::GetActionUrl | Flow::SyncOnboardingStatus | Flow::ResetTrackingId => {
Self::ConnectorOnboarding Self::ConnectorOnboarding

View File

@ -7,7 +7,7 @@ use crate::{
core::{api_locking, user_role as user_role_core}, core::{api_locking, user_role as user_role_core},
services::{ services::{
api, api,
authentication::{self as auth}, authentication::{self as auth, UserFromToken},
authorization::permissions::Permission, authorization::permissions::Permission,
}, },
}; };
@ -64,6 +64,20 @@ pub async fn get_role(
.await .await
} }
pub async fn get_role_from_token(state: web::Data<AppState>, 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( pub async fn update_user_role(
state: web::Data<AppState>, state: web::Data<AppState>,
req: HttpRequest, req: HttpRequest,

View File

@ -15,16 +15,13 @@ pub struct PermissionInfo {
impl PermissionInfo { impl PermissionInfo {
pub fn new(permissions: &[Permission]) -> Vec<Self> { pub fn new(permissions: &[Permission]) -> Vec<Self> {
let mut permission_infos = Vec::with_capacity(permissions.len()); permissions
for permission in permissions { .iter()
if let Some(description) = Permission::get_permission_description(permission) { .map(|&per| Self {
permission_infos.push(Self { description: Permission::get_permission_description(&per),
enum_name: permission.clone(), enum_name: per,
description, })
}) .collect()
}
}
permission_infos
} }
} }
@ -43,6 +40,7 @@ pub enum PermissionModule {
Files, Files,
ThreeDsDecisionManager, ThreeDsDecisionManager,
SurchargeDecisionManager, SurchargeDecisionManager,
AccountCreate,
} }
impl PermissionModule { 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::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::Files => "Permissions for uploading, deleting and viewing files for disputes",
Self::ThreeDsDecisionManager => "View and configure 3DS decision rules configured for a merchant", 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, Permission::SurchargeDecisionManagerRead,
]), ]),
}, },
PermissionModule::AccountCreate => Self {
module: module_name,
description,
permissions: PermissionInfo::new(&[Permission::MerchantAccountCreate]),
},
} }
} }
} }

View File

@ -1,6 +1,6 @@
use strum::Display; use strum::Display;
#[derive(PartialEq, Display, Clone, Debug)] #[derive(PartialEq, Display, Clone, Debug, Copy)]
pub enum Permission { pub enum Permission {
PaymentRead, PaymentRead,
PaymentWrite, PaymentWrite,
@ -34,45 +34,43 @@ pub enum Permission {
} }
impl Permission { impl Permission {
pub fn get_permission_description(&self) -> Option<&'static str> { pub fn get_permission_description(&self) -> &'static str {
match self { match self {
Self::PaymentRead => Some("View all payments"), Self::PaymentRead => "View all payments",
Self::PaymentWrite => Some("Create payment, download payments data"), Self::PaymentWrite => "Create payment, download payments data",
Self::RefundRead => Some("View all refunds"), Self::RefundRead => "View all refunds",
Self::RefundWrite => Some("Create refund, download refunds data"), Self::RefundWrite => "Create refund, download refunds data",
Self::ApiKeyRead => Some("View API keys (masked generated for the system"), Self::ApiKeyRead => "View API keys (masked generated for the system",
Self::ApiKeyWrite => Some("Create and update API keys"), Self::ApiKeyWrite => "Create and update API keys",
Self::MerchantAccountRead => Some("View merchant account details"), Self::MerchantAccountRead => "View merchant account details",
Self::MerchantAccountWrite => { 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 => { Self::MerchantConnectorAccountWrite => {
Some("Create, update, verify and delete connector configurations") "Create, update, verify and delete connector configurations"
} }
Self::ForexRead => Some("Query Forex data"), Self::ForexRead => "Query Forex data",
Self::RoutingRead => Some("View routing configuration"), Self::RoutingRead => "View routing configuration",
Self::RoutingWrite => Some("Create and activate routing configurations"), Self::RoutingWrite => "Create and activate routing configurations",
Self::DisputeRead => Some("View disputes"), Self::DisputeRead => "View disputes",
Self::DisputeWrite => Some("Create and update disputes"), Self::DisputeWrite => "Create and update disputes",
Self::MandateRead => Some("View mandates"), Self::MandateRead => "View mandates",
Self::MandateWrite => Some("Create and update mandates"), Self::MandateWrite => "Create and update mandates",
Self::CustomerRead => Some("View customers"), Self::CustomerRead => "View customers",
Self::CustomerWrite => Some("Create, update and delete customers"), Self::CustomerWrite => "Create, update and delete customers",
Self::FileRead => Some("View files"), Self::FileRead => "View files",
Self::FileWrite => Some("Create, update and delete files"), Self::FileWrite => "Create, update and delete files",
Self::Analytics => Some("Access to analytics module"), Self::Analytics => "Access to analytics module",
Self::ThreeDsDecisionManagerWrite => Some("Create and update 3DS decision rules"), Self::ThreeDsDecisionManagerWrite => "Create and update 3DS decision rules",
Self::ThreeDsDecisionManagerRead => { Self::ThreeDsDecisionManagerRead => {
Some("View all 3DS decision rules configured for a merchant") "View all 3DS decision rules configured for a merchant"
} }
Self::SurchargeDecisionManagerWrite => { Self::SurchargeDecisionManagerWrite => "Create and update the surcharge decision rules",
Some("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::SurchargeDecisionManagerRead => Some("View all the surcharge decision rules"), Self::UsersWrite => "Invite users, assign and update roles",
Self::UsersRead => Some("View all the users for a merchant"), Self::MerchantAccountCreate => "Create merchant account",
Self::UsersWrite => Some("Invite users, assign and update roles"),
Self::MerchantAccountCreate => None,
} }
} }
} }

View File

@ -762,19 +762,13 @@ impl UserFromStorage {
} }
} }
impl TryFrom<info::ModuleInfo> for user_role_api::ModuleInfo { impl From<info::ModuleInfo> for user_role_api::ModuleInfo {
type Error = (); fn from(value: info::ModuleInfo) -> Self {
fn try_from(value: info::ModuleInfo) -> Result<Self, Self::Error> { Self {
let mut permissions = Vec::with_capacity(value.permissions.len());
for permission in value.permissions {
let permission = permission.try_into()?;
permissions.push(permission);
}
Ok(Self {
module: value.module.into(), module: value.module.into(),
description: value.description, description: value.description,
permissions, permissions: value.permissions.into_iter().map(Into::into).collect(),
}) }
} }
} }
@ -794,18 +788,17 @@ impl From<info::PermissionModule> for user_role_api::PermissionModule {
info::PermissionModule::Files => Self::Files, info::PermissionModule::Files => Self::Files,
info::PermissionModule::ThreeDsDecisionManager => Self::ThreeDsDecisionManager, info::PermissionModule::ThreeDsDecisionManager => Self::ThreeDsDecisionManager,
info::PermissionModule::SurchargeDecisionManager => Self::SurchargeDecisionManager, info::PermissionModule::SurchargeDecisionManager => Self::SurchargeDecisionManager,
info::PermissionModule::AccountCreate => Self::AccountCreate,
} }
} }
} }
impl TryFrom<info::PermissionInfo> for user_role_api::PermissionInfo { impl From<info::PermissionInfo> for user_role_api::PermissionInfo {
type Error = (); fn from(value: info::PermissionInfo) -> Self {
fn try_from(value: info::PermissionInfo) -> Result<Self, Self::Error> { Self {
let enum_name = (&value.enum_name).try_into()?; enum_name: value.enum_name.into(),
Ok(Self {
enum_name,
description: value.description, description: value.description,
}) }
} }
} }

View File

@ -1,7 +1,6 @@
use api_models::user_role as user_role_api; use api_models::user_role as user_role_api;
use diesel_models::enums::UserStatus; use diesel_models::enums::UserStatus;
use error_stack::ResultExt; use error_stack::ResultExt;
use router_env::logger;
use crate::{ use crate::{
consts, consts,
@ -44,52 +43,50 @@ pub fn validate_role_id(role_id: &str) -> UserResult<()> {
pub fn get_role_name_and_permission_response( pub fn get_role_name_and_permission_response(
role_info: &RoleInfo, role_info: &RoleInfo,
) -> Option<(Vec<user_role_api::Permission>, &'static str)> { ) -> Option<(Vec<user_role_api::Permission>, &'static str)> {
role_info role_info.get_name().map(|name| {
.get_permissions() (
.iter() role_info
.map(TryInto::try_into) .get_permissions()
.collect::<Result<Vec<user_role_api::Permission>, _>>() .iter()
.ok() .map(|&per| per.into())
.zip(role_info.get_name()) .collect::<Vec<user_role_api::Permission>>(),
name,
)
})
} }
impl TryFrom<&Permission> for user_role_api::Permission { impl From<Permission> for user_role_api::Permission {
type Error = (); fn from(value: Permission) -> Self {
fn try_from(value: &Permission) -> Result<Self, Self::Error> {
match value { match value {
Permission::PaymentRead => Ok(Self::PaymentRead), Permission::PaymentRead => Self::PaymentRead,
Permission::PaymentWrite => Ok(Self::PaymentWrite), Permission::PaymentWrite => Self::PaymentWrite,
Permission::RefundRead => Ok(Self::RefundRead), Permission::RefundRead => Self::RefundRead,
Permission::RefundWrite => Ok(Self::RefundWrite), Permission::RefundWrite => Self::RefundWrite,
Permission::ApiKeyRead => Ok(Self::ApiKeyRead), Permission::ApiKeyRead => Self::ApiKeyRead,
Permission::ApiKeyWrite => Ok(Self::ApiKeyWrite), Permission::ApiKeyWrite => Self::ApiKeyWrite,
Permission::MerchantAccountRead => Ok(Self::MerchantAccountRead), Permission::MerchantAccountRead => Self::MerchantAccountRead,
Permission::MerchantAccountWrite => Ok(Self::MerchantAccountWrite), Permission::MerchantAccountWrite => Self::MerchantAccountWrite,
Permission::MerchantConnectorAccountRead => Ok(Self::MerchantConnectorAccountRead), Permission::MerchantConnectorAccountRead => Self::MerchantConnectorAccountRead,
Permission::MerchantConnectorAccountWrite => Ok(Self::MerchantConnectorAccountWrite), Permission::MerchantConnectorAccountWrite => Self::MerchantConnectorAccountWrite,
Permission::ForexRead => Ok(Self::ForexRead), Permission::ForexRead => Self::ForexRead,
Permission::RoutingRead => Ok(Self::RoutingRead), Permission::RoutingRead => Self::RoutingRead,
Permission::RoutingWrite => Ok(Self::RoutingWrite), Permission::RoutingWrite => Self::RoutingWrite,
Permission::DisputeRead => Ok(Self::DisputeRead), Permission::DisputeRead => Self::DisputeRead,
Permission::DisputeWrite => Ok(Self::DisputeWrite), Permission::DisputeWrite => Self::DisputeWrite,
Permission::MandateRead => Ok(Self::MandateRead), Permission::MandateRead => Self::MandateRead,
Permission::MandateWrite => Ok(Self::MandateWrite), Permission::MandateWrite => Self::MandateWrite,
Permission::CustomerRead => Ok(Self::CustomerRead), Permission::CustomerRead => Self::CustomerRead,
Permission::CustomerWrite => Ok(Self::CustomerWrite), Permission::CustomerWrite => Self::CustomerWrite,
Permission::FileRead => Ok(Self::FileRead), Permission::FileRead => Self::FileRead,
Permission::FileWrite => Ok(Self::FileWrite), Permission::FileWrite => Self::FileWrite,
Permission::Analytics => Ok(Self::Analytics), Permission::Analytics => Self::Analytics,
Permission::ThreeDsDecisionManagerWrite => Ok(Self::ThreeDsDecisionManagerWrite), Permission::ThreeDsDecisionManagerWrite => Self::ThreeDsDecisionManagerWrite,
Permission::ThreeDsDecisionManagerRead => Ok(Self::ThreeDsDecisionManagerRead), Permission::ThreeDsDecisionManagerRead => Self::ThreeDsDecisionManagerRead,
Permission::SurchargeDecisionManagerWrite => Ok(Self::SurchargeDecisionManagerWrite), Permission::SurchargeDecisionManagerWrite => Self::SurchargeDecisionManagerWrite,
Permission::SurchargeDecisionManagerRead => Ok(Self::SurchargeDecisionManagerRead), Permission::SurchargeDecisionManagerRead => Self::SurchargeDecisionManagerRead,
Permission::UsersRead => Ok(Self::UsersRead), Permission::UsersRead => Self::UsersRead,
Permission::UsersWrite => Ok(Self::UsersWrite), Permission::UsersWrite => Self::UsersWrite,
Permission::MerchantAccountCreate => Self::MerchantAccountCreate,
Permission::MerchantAccountCreate => {
logger::error!("Invalid use of internal permission");
Err(())
}
} }
} }
} }

View File

@ -297,6 +297,8 @@ pub enum Flow {
ListRoles, ListRoles,
/// Get role /// Get role
GetRole, GetRole,
/// Get role from token
GetRoleFromToken,
/// Update user role /// Update user role
UpdateUserRole, UpdateUserRole,
/// Create merchant account for user in a org /// Create merchant account for user in a org