mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 05:17:02 +08:00
feat(user): setup roles table with queries (#3691)
This commit is contained in:
@ -17,7 +17,8 @@ pub mod diesel_exports {
|
|||||||
DbProcessTrackerStatus as ProcessTrackerStatus, DbReconStatus as ReconStatus,
|
DbProcessTrackerStatus as ProcessTrackerStatus, DbReconStatus as ReconStatus,
|
||||||
DbRefundStatus as RefundStatus, DbRefundType as RefundType,
|
DbRefundStatus as RefundStatus, DbRefundType as RefundType,
|
||||||
DbRequestIncrementalAuthorization as RequestIncrementalAuthorization,
|
DbRequestIncrementalAuthorization as RequestIncrementalAuthorization,
|
||||||
DbRoutingAlgorithmKind as RoutingAlgorithmKind, DbUserStatus as UserStatus,
|
DbRoleScope as RoleScope, DbRoutingAlgorithmKind as RoutingAlgorithmKind,
|
||||||
|
DbUserStatus as UserStatus,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub use common_enums::*;
|
pub use common_enums::*;
|
||||||
@ -500,3 +501,53 @@ pub enum DashboardMetadata {
|
|||||||
IsMultipleConfiguration,
|
IsMultipleConfiguration,
|
||||||
IsChangePasswordRequired,
|
IsChangePasswordRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
Eq,
|
||||||
|
PartialEq,
|
||||||
|
serde::Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
strum::Display,
|
||||||
|
strum::EnumString,
|
||||||
|
frunk::LabelledGeneric,
|
||||||
|
)]
|
||||||
|
#[diesel_enum(storage_type = "db_enum")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
pub enum RoleScope {
|
||||||
|
Merchant,
|
||||||
|
Organization,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
Eq,
|
||||||
|
PartialEq,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
strum::Display,
|
||||||
|
strum::EnumString,
|
||||||
|
frunk::LabelledGeneric,
|
||||||
|
)]
|
||||||
|
#[diesel_enum(storage_type = "text")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
pub enum PermissionGroup {
|
||||||
|
OperationsView,
|
||||||
|
OperationsManage,
|
||||||
|
ConnectorsView,
|
||||||
|
ConnectorsManage,
|
||||||
|
WorkflowsView,
|
||||||
|
WorkflowsManage,
|
||||||
|
AnalyticsView,
|
||||||
|
UsersView,
|
||||||
|
UsersManage,
|
||||||
|
MerchantDetailsView,
|
||||||
|
MerchantDetailsManage,
|
||||||
|
OrganizationManage,
|
||||||
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ pub mod process_tracker;
|
|||||||
pub mod query;
|
pub mod query;
|
||||||
pub mod refund;
|
pub mod refund;
|
||||||
pub mod reverse_lookup;
|
pub mod reverse_lookup;
|
||||||
|
pub mod role;
|
||||||
pub mod routing_algorithm;
|
pub mod routing_algorithm;
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
|
|||||||
@ -32,6 +32,7 @@ pub mod payouts;
|
|||||||
pub mod process_tracker;
|
pub mod process_tracker;
|
||||||
pub mod refund;
|
pub mod refund;
|
||||||
pub mod reverse_lookup;
|
pub mod reverse_lookup;
|
||||||
|
pub mod role;
|
||||||
pub mod routing_algorithm;
|
pub mod routing_algorithm;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod user_role;
|
pub mod user_role;
|
||||||
|
|||||||
68
crates/diesel_models/src/query/role.rs
Normal file
68
crates/diesel_models/src/query/role.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};
|
||||||
|
use router_env::tracing::{self, instrument};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
enums::RoleScope, query::generics, role::*, schema::roles::dsl, PgPooledConn, StorageResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl RoleNew {
|
||||||
|
#[instrument(skip(conn))]
|
||||||
|
pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Role> {
|
||||||
|
generics::generic_insert(conn, self).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Role {
|
||||||
|
pub async fn find_by_role_id(conn: &PgPooledConn, role_id: &str) -> StorageResult<Self> {
|
||||||
|
generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
|
||||||
|
conn,
|
||||||
|
dsl::role_id.eq(role_id.to_owned()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_by_role_id(
|
||||||
|
conn: &PgPooledConn,
|
||||||
|
role_id: &str,
|
||||||
|
role_update: RoleUpdate,
|
||||||
|
) -> StorageResult<Self> {
|
||||||
|
generics::generic_update_with_unique_predicate_get_result::<
|
||||||
|
<Self as HasTable>::Table,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
>(
|
||||||
|
conn,
|
||||||
|
dsl::role_id.eq(role_id.to_owned()),
|
||||||
|
RoleUpdateInternal::from(role_update),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_by_role_id(conn: &PgPooledConn, role_id: &str) -> StorageResult<Self> {
|
||||||
|
generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
|
||||||
|
conn,
|
||||||
|
dsl::role_id.eq(role_id.to_owned()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_roles(
|
||||||
|
conn: &PgPooledConn,
|
||||||
|
merchant_id: &str,
|
||||||
|
org_id: &str,
|
||||||
|
) -> StorageResult<Vec<Self>> {
|
||||||
|
let predicate = dsl::merchant_id.eq(merchant_id.to_owned()).or(dsl::org_id
|
||||||
|
.eq(org_id.to_owned())
|
||||||
|
.and(dsl::scope.eq(RoleScope::Organization)));
|
||||||
|
|
||||||
|
generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
|
||||||
|
conn,
|
||||||
|
predicate,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(dsl::last_modified_at.asc()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
83
crates/diesel_models/src/role.rs
Normal file
83
crates/diesel_models/src/role.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
|
||||||
|
use time::PrimitiveDateTime;
|
||||||
|
|
||||||
|
use crate::{enums, schema::roles};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Identifiable, Queryable)]
|
||||||
|
#[diesel(table_name = roles)]
|
||||||
|
pub struct Role {
|
||||||
|
pub id: i32,
|
||||||
|
pub role_name: String,
|
||||||
|
pub role_id: String,
|
||||||
|
pub merchant_id: String,
|
||||||
|
pub org_id: String,
|
||||||
|
#[diesel(deserialize_as = super::DieselArray<enums::PermissionGroup>)]
|
||||||
|
pub groups: Vec<enums::PermissionGroup>,
|
||||||
|
pub scope: enums::RoleScope,
|
||||||
|
pub created_at: PrimitiveDateTime,
|
||||||
|
pub created_by: String,
|
||||||
|
pub last_modified_at: PrimitiveDateTime,
|
||||||
|
pub last_modified_by: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(router_derive::Setter, Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
|
||||||
|
#[diesel(table_name = roles)]
|
||||||
|
pub struct RoleNew {
|
||||||
|
pub role_name: String,
|
||||||
|
pub role_id: String,
|
||||||
|
pub merchant_id: String,
|
||||||
|
pub org_id: String,
|
||||||
|
#[diesel(deserialize_as = super::DieselArray<enums::PermissionGroup>)]
|
||||||
|
pub groups: Vec<enums::PermissionGroup>,
|
||||||
|
pub scope: enums::RoleScope,
|
||||||
|
pub created_at: PrimitiveDateTime,
|
||||||
|
pub created_by: String,
|
||||||
|
pub last_modified_at: PrimitiveDateTime,
|
||||||
|
pub last_modified_by: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
|
||||||
|
#[diesel(table_name = roles)]
|
||||||
|
pub struct RoleUpdateInternal {
|
||||||
|
groups: Option<Vec<enums::PermissionGroup>>,
|
||||||
|
role_name: Option<String>,
|
||||||
|
last_modified_by: String,
|
||||||
|
last_modified_at: PrimitiveDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RoleUpdate {
|
||||||
|
UpdateGroup {
|
||||||
|
groups: Vec<enums::PermissionGroup>,
|
||||||
|
last_modified_by: String,
|
||||||
|
},
|
||||||
|
UpdateRoleName {
|
||||||
|
role_name: String,
|
||||||
|
last_modified_by: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RoleUpdate> for RoleUpdateInternal {
|
||||||
|
fn from(value: RoleUpdate) -> Self {
|
||||||
|
let last_modified_at = common_utils::date_time::now();
|
||||||
|
match value {
|
||||||
|
RoleUpdate::UpdateGroup {
|
||||||
|
groups,
|
||||||
|
last_modified_by,
|
||||||
|
} => Self {
|
||||||
|
groups: Some(groups),
|
||||||
|
role_name: None,
|
||||||
|
last_modified_at,
|
||||||
|
last_modified_by,
|
||||||
|
},
|
||||||
|
RoleUpdate::UpdateRoleName {
|
||||||
|
role_name,
|
||||||
|
last_modified_by,
|
||||||
|
} => Self {
|
||||||
|
groups: None,
|
||||||
|
role_name: Some(role_name),
|
||||||
|
last_modified_at,
|
||||||
|
last_modified_by,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -994,6 +994,31 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
use diesel::sql_types::*;
|
||||||
|
use crate::enums::diesel_exports::*;
|
||||||
|
|
||||||
|
roles (id) {
|
||||||
|
id -> Int4,
|
||||||
|
#[max_length = 64]
|
||||||
|
role_name -> Varchar,
|
||||||
|
#[max_length = 64]
|
||||||
|
role_id -> Varchar,
|
||||||
|
#[max_length = 64]
|
||||||
|
merchant_id -> Varchar,
|
||||||
|
#[max_length = 64]
|
||||||
|
org_id -> Varchar,
|
||||||
|
groups -> Array<Nullable<Text>>,
|
||||||
|
scope -> RoleScope,
|
||||||
|
created_at -> Timestamp,
|
||||||
|
#[max_length = 64]
|
||||||
|
created_by -> Varchar,
|
||||||
|
last_modified_at -> Timestamp,
|
||||||
|
#[max_length = 64]
|
||||||
|
last_modified_by -> Varchar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
use diesel::sql_types::*;
|
use diesel::sql_types::*;
|
||||||
use crate::enums::diesel_exports::*;
|
use crate::enums::diesel_exports::*;
|
||||||
@ -1095,6 +1120,7 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||||||
process_tracker,
|
process_tracker,
|
||||||
refund,
|
refund,
|
||||||
reverse_lookup,
|
reverse_lookup,
|
||||||
|
roles,
|
||||||
routing_algorithm,
|
routing_algorithm,
|
||||||
user_roles,
|
user_roles,
|
||||||
users,
|
users,
|
||||||
|
|||||||
@ -31,6 +31,7 @@ pub mod payout_attempt;
|
|||||||
pub mod payouts;
|
pub mod payouts;
|
||||||
pub mod refund;
|
pub mod refund;
|
||||||
pub mod reverse_lookup;
|
pub mod reverse_lookup;
|
||||||
|
pub mod role;
|
||||||
pub mod routing_algorithm;
|
pub mod routing_algorithm;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod user_role;
|
pub mod user_role;
|
||||||
@ -111,6 +112,7 @@ pub trait StorageInterface:
|
|||||||
+ authorization::AuthorizationInterface
|
+ authorization::AuthorizationInterface
|
||||||
+ user::sample_data::BatchSampleDataInterface
|
+ user::sample_data::BatchSampleDataInterface
|
||||||
+ health_check::HealthCheckDbInterface
|
+ health_check::HealthCheckDbInterface
|
||||||
|
+ role::RoleInterface
|
||||||
+ 'static
|
+ 'static
|
||||||
{
|
{
|
||||||
fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>;
|
fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ use time::PrimitiveDateTime;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
dashboard_metadata::DashboardMetadataInterface,
|
dashboard_metadata::DashboardMetadataInterface,
|
||||||
|
role::RoleInterface,
|
||||||
user::{sample_data::BatchSampleDataInterface, UserInterface},
|
user::{sample_data::BatchSampleDataInterface, UserInterface},
|
||||||
user_role::UserRoleInterface,
|
user_role::UserRoleInterface,
|
||||||
};
|
};
|
||||||
@ -2256,3 +2257,45 @@ impl HealthCheckDbInterface for KafkaStore {
|
|||||||
self.diesel_store.health_check_db().await
|
self.diesel_store.health_check_db().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl RoleInterface for KafkaStore {
|
||||||
|
async fn insert_role(
|
||||||
|
&self,
|
||||||
|
role: storage::RoleNew,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
self.diesel_store.insert_role(role).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
self.diesel_store.find_role_by_role_id(role_id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
role_update: storage::RoleUpdate,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
self.diesel_store
|
||||||
|
.update_role_by_role_id(role_id, role_update)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
self.diesel_store.delete_role_by_role_id(role_id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_all_roles(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
org_id: &str,
|
||||||
|
) -> CustomResult<Vec<storage::Role>, errors::StorageError> {
|
||||||
|
self.diesel_store.list_all_roles(merchant_id, org_id).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
236
crates/router/src/db/role.rs
Normal file
236
crates/router/src/db/role.rs
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
use diesel_models::role as storage;
|
||||||
|
use error_stack::{IntoReport, ResultExt};
|
||||||
|
|
||||||
|
use super::MockDb;
|
||||||
|
use crate::{
|
||||||
|
connection,
|
||||||
|
core::errors::{self, CustomResult},
|
||||||
|
services::Store,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait RoleInterface {
|
||||||
|
async fn insert_role(
|
||||||
|
&self,
|
||||||
|
role: storage::RoleNew,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError>;
|
||||||
|
|
||||||
|
async fn find_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError>;
|
||||||
|
|
||||||
|
async fn update_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
role_update: storage::RoleUpdate,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError>;
|
||||||
|
|
||||||
|
async fn delete_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError>;
|
||||||
|
|
||||||
|
async fn list_all_roles(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
org_id: &str,
|
||||||
|
) -> CustomResult<Vec<storage::Role>, errors::StorageError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl RoleInterface for Store {
|
||||||
|
async fn insert_role(
|
||||||
|
&self,
|
||||||
|
role: storage::RoleNew,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
|
role.insert(&conn).await.map_err(Into::into).into_report()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
|
storage::Role::find_by_role_id(&conn, role_id)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
.into_report()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
role_update: storage::RoleUpdate,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
|
storage::Role::update_by_role_id(&conn, role_id, role_update)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
.into_report()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
|
storage::Role::delete_by_role_id(&conn, role_id)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
.into_report()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_all_roles(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
org_id: &str,
|
||||||
|
) -> CustomResult<Vec<storage::Role>, errors::StorageError> {
|
||||||
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
|
storage::Role::list_roles(&conn, merchant_id, org_id)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
.into_report()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl RoleInterface for MockDb {
|
||||||
|
async fn insert_role(
|
||||||
|
&self,
|
||||||
|
role: storage::RoleNew,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let mut roles = self.roles.lock().await;
|
||||||
|
if roles
|
||||||
|
.iter()
|
||||||
|
.any(|role_inner| role_inner.role_id == role.role_id)
|
||||||
|
{
|
||||||
|
Err(errors::StorageError::DuplicateValue {
|
||||||
|
entity: "role_id",
|
||||||
|
key: None,
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
let role = storage::Role {
|
||||||
|
id: roles
|
||||||
|
.len()
|
||||||
|
.try_into()
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::StorageError::MockDbError)?,
|
||||||
|
role_name: role.role_name,
|
||||||
|
role_id: role.role_id,
|
||||||
|
merchant_id: role.merchant_id,
|
||||||
|
org_id: role.org_id,
|
||||||
|
groups: role.groups,
|
||||||
|
scope: role.scope,
|
||||||
|
created_by: role.created_by,
|
||||||
|
created_at: role.created_at,
|
||||||
|
last_modified_at: role.last_modified_at,
|
||||||
|
last_modified_by: role.last_modified_by,
|
||||||
|
};
|
||||||
|
roles.push(role.clone());
|
||||||
|
Ok(role)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let roles = self.roles.lock().await;
|
||||||
|
roles
|
||||||
|
.iter()
|
||||||
|
.find(|role| role.role_id == role_id)
|
||||||
|
.cloned()
|
||||||
|
.ok_or(
|
||||||
|
errors::StorageError::ValueNotFound(format!(
|
||||||
|
"No role available role_id = {role_id}"
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
role_update: storage::RoleUpdate,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let mut roles = self.roles.lock().await;
|
||||||
|
let last_modified_at = common_utils::date_time::now();
|
||||||
|
|
||||||
|
roles
|
||||||
|
.iter_mut()
|
||||||
|
.find(|role| role.role_id == role_id)
|
||||||
|
.map(|role| {
|
||||||
|
*role = match role_update {
|
||||||
|
storage::RoleUpdate::UpdateGroup {
|
||||||
|
groups,
|
||||||
|
last_modified_by,
|
||||||
|
} => storage::Role {
|
||||||
|
groups,
|
||||||
|
last_modified_by,
|
||||||
|
last_modified_at,
|
||||||
|
..role.to_owned()
|
||||||
|
},
|
||||||
|
storage::RoleUpdate::UpdateRoleName {
|
||||||
|
role_name,
|
||||||
|
last_modified_by,
|
||||||
|
} => storage::Role {
|
||||||
|
role_name,
|
||||||
|
last_modified_at,
|
||||||
|
last_modified_by,
|
||||||
|
..role.to_owned()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
role.to_owned()
|
||||||
|
})
|
||||||
|
.ok_or(
|
||||||
|
errors::StorageError::ValueNotFound(format!(
|
||||||
|
"No role available for role_id = {role_id}"
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_role_by_role_id(
|
||||||
|
&self,
|
||||||
|
role_id: &str,
|
||||||
|
) -> CustomResult<storage::Role, errors::StorageError> {
|
||||||
|
let mut roles = self.roles.lock().await;
|
||||||
|
let role_index = roles
|
||||||
|
.iter()
|
||||||
|
.position(|role| role.role_id == role_id)
|
||||||
|
.ok_or(errors::StorageError::ValueNotFound(format!(
|
||||||
|
"No role available for role_id = {role_id}"
|
||||||
|
)))?;
|
||||||
|
|
||||||
|
Ok(roles.remove(role_index))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_all_roles(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
org_id: &str,
|
||||||
|
) -> CustomResult<Vec<storage::Role>, errors::StorageError> {
|
||||||
|
let roles = self.roles.lock().await;
|
||||||
|
|
||||||
|
let roles_list: Vec<_> = roles
|
||||||
|
.iter()
|
||||||
|
.filter(|role| {
|
||||||
|
role.merchant_id == merchant_id
|
||||||
|
|| (role.org_id == org_id
|
||||||
|
&& role.scope == diesel_models::enums::RoleScope::Organization)
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if roles_list.is_empty() {
|
||||||
|
return Err(errors::StorageError::ValueNotFound(format!(
|
||||||
|
"No role found for merchant id = {} and org_id = {}",
|
||||||
|
merchant_id, org_id
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(roles_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,6 +31,7 @@ pub mod payout_attempt;
|
|||||||
pub mod payouts;
|
pub mod payouts;
|
||||||
pub mod refund;
|
pub mod refund;
|
||||||
pub mod reverse_lookup;
|
pub mod reverse_lookup;
|
||||||
|
pub mod role;
|
||||||
pub mod routing_algorithm;
|
pub mod routing_algorithm;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod user_role;
|
pub mod user_role;
|
||||||
@ -51,7 +52,8 @@ pub use self::{
|
|||||||
dashboard_metadata::*, dispute::*, ephemeral_key::*, events::*, file::*, fraud_check::*,
|
dashboard_metadata::*, dispute::*, ephemeral_key::*, events::*, file::*, fraud_check::*,
|
||||||
gsm::*, locker_mock_up::*, mandate::*, merchant_account::*, merchant_connector_account::*,
|
gsm::*, locker_mock_up::*, mandate::*, merchant_account::*, merchant_connector_account::*,
|
||||||
merchant_key_store::*, payment_link::*, payment_method::*, payout_attempt::*, payouts::*,
|
merchant_key_store::*, payment_link::*, payment_method::*, payout_attempt::*, payouts::*,
|
||||||
process_tracker::*, refund::*, reverse_lookup::*, routing_algorithm::*, user::*, user_role::*,
|
process_tracker::*, refund::*, reverse_lookup::*, role::*, routing_algorithm::*, user::*,
|
||||||
|
user_role::*,
|
||||||
};
|
};
|
||||||
use crate::types::api::routing;
|
use crate::types::api::routing;
|
||||||
|
|
||||||
|
|||||||
1
crates/router/src/types/storage/role.rs
Normal file
1
crates/router/src/types/storage/role.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub use diesel_models::role::*;
|
||||||
@ -45,6 +45,7 @@ pub struct MockDb {
|
|||||||
pub user_roles: Arc<Mutex<Vec<store::user_role::UserRole>>>,
|
pub user_roles: Arc<Mutex<Vec<store::user_role::UserRole>>>,
|
||||||
pub authorizations: Arc<Mutex<Vec<store::authorization::Authorization>>>,
|
pub authorizations: Arc<Mutex<Vec<store::authorization::Authorization>>>,
|
||||||
pub dashboard_metadata: Arc<Mutex<Vec<store::user::dashboard_metadata::DashboardMetadata>>>,
|
pub dashboard_metadata: Arc<Mutex<Vec<store::user::dashboard_metadata::DashboardMetadata>>>,
|
||||||
|
pub roles: Arc<Mutex<Vec<store::role::Role>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockDb {
|
impl MockDb {
|
||||||
@ -82,6 +83,7 @@ impl MockDb {
|
|||||||
user_roles: Default::default(),
|
user_roles: Default::default(),
|
||||||
authorizations: Default::default(),
|
authorizations: Default::default(),
|
||||||
dashboard_metadata: Default::default(),
|
dashboard_metadata: Default::default(),
|
||||||
|
roles: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
migrations/2024-02-14-092225_create_roles_table/down.sql
Normal file
6
migrations/2024-02-14-092225_create_roles_table/down.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
-- This file should undo anything in `up.sql`
|
||||||
|
DROP INDEX IF EXISTS role_id_index;
|
||||||
|
DROP INDEX IF EXISTS roles_merchant_org_index;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS roles;
|
||||||
|
DROP TYPE "RoleScope";
|
||||||
19
migrations/2024-02-14-092225_create_roles_table/up.sql
Normal file
19
migrations/2024-02-14-092225_create_roles_table/up.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- Your SQL goes here
|
||||||
|
CREATE TYPE "RoleScope" AS ENUM ('merchant','organization');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS roles (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
role_name VARCHAR(64) NOT NULL,
|
||||||
|
role_id VARCHAR(64) NOT NULL UNIQUE,
|
||||||
|
merchant_id VARCHAR(64) NOT NULL,
|
||||||
|
org_id VARCHAR(64) NOT NULL,
|
||||||
|
groups TEXT[] NOT NULL,
|
||||||
|
scope "RoleScope" NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
created_by VARCHAR(64) NOT NULL,
|
||||||
|
last_modified_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
last_modified_by VARCHAR(64) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS role_id_index ON roles (role_id);
|
||||||
|
CREATE INDEX roles_merchant_org_index ON roles (merchant_id, org_id);
|
||||||
Reference in New Issue
Block a user