Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/api_models/src/user_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum Permission {
SurchargeDecisionManagerRead,
UsersRead,
UsersWrite,
MerchantAccountCreate,
}

#[derive(Debug, serde::Serialize)]
Expand All @@ -60,6 +61,7 @@ pub enum PermissionModule {
Files,
ThreeDsDecisionManager,
SurchargeDecisionManager,
AccountCreate,
}

#[derive(Debug, serde::Serialize)]
Expand Down
18 changes: 17 additions & 1 deletion crates/router/src/core/user_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
),
))
Expand Down Expand Up @@ -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<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(
state: AppState,
user_from_token: auth::UserFromToken,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
8 changes: 5 additions & 3 deletions crates/router/src/routes/lock_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,11 @@ impl From<Flow> 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
Expand Down
16 changes: 15 additions & 1 deletion crates/router/src/routes/user_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
};
Expand Down Expand Up @@ -64,6 +64,20 @@ pub async fn get_role(
.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(
state: web::Data<AppState>,
req: HttpRequest,
Expand Down
26 changes: 15 additions & 11 deletions crates/router/src/services/authorization/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@ pub struct PermissionInfo {

impl PermissionInfo {
pub fn new(permissions: &[Permission]) -> Vec<Self> {
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()
}
}

Expand All @@ -43,6 +40,7 @@ pub enum PermissionModule {
Files,
ThreeDsDecisionManager,
SurchargeDecisionManager,
AccountCreate,
}

impl PermissionModule {
Expand All @@ -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"
}
}
}
Expand Down Expand Up @@ -173,6 +172,11 @@ impl ModuleInfo {
Permission::SurchargeDecisionManagerRead,
]),
},
PermissionModule::AccountCreate => Self {
module: module_name,
description,
permissions: PermissionInfo::new(&[Permission::MerchantAccountCreate]),
},
}
}
}
64 changes: 31 additions & 33 deletions crates/router/src/services/authorization/permissions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use strum::Display;

#[derive(PartialEq, Display, Clone, Debug)]
#[derive(PartialEq, Display, Clone, Debug, Copy)]
pub enum Permission {
PaymentRead,
PaymentWrite,
Expand Down Expand Up @@ -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",
}
}
}
29 changes: 11 additions & 18 deletions crates/router/src/types/domain/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,19 +762,13 @@ impl UserFromStorage {
}
}

impl TryFrom<info::ModuleInfo> for user_role_api::ModuleInfo {
type Error = ();
fn try_from(value: info::ModuleInfo) -> Result<Self, Self::Error> {
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<info::ModuleInfo> 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(),
}
}
}

Expand All @@ -794,18 +788,17 @@ impl From<info::PermissionModule> 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<info::PermissionInfo> for user_role_api::PermissionInfo {
type Error = ();
fn try_from(value: info::PermissionInfo) -> Result<Self, Self::Error> {
let enum_name = (&value.enum_name).try_into()?;
Ok(Self {
enum_name,
impl From<info::PermissionInfo> for user_role_api::PermissionInfo {
fn from(value: info::PermissionInfo) -> Self {
Self {
enum_name: value.enum_name.into(),
description: value.description,
})
}
}
}

Expand Down
85 changes: 41 additions & 44 deletions crates/router/src/utils/user_role.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<user_role_api::Permission>, &'static str)> {
role_info
.get_permissions()
.iter()
.map(TryInto::try_into)
.collect::<Result<Vec<user_role_api::Permission>, _>>()
.ok()
.zip(role_info.get_name())
role_info.get_name().map(|name| {
(
role_info
.get_permissions()
.iter()
.map(|&per| per.into())
.collect::<Vec<user_role_api::Permission>>(),
name,
)
})
}

impl TryFrom<&Permission> for user_role_api::Permission {
type Error = ();
fn try_from(value: &Permission) -> Result<Self, Self::Error> {
impl From<Permission> 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,
}
}
}
2 changes: 2 additions & 0 deletions crates/router_env/src/logger/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading