diff --git a/Cargo.lock b/Cargo.lock index 1ebf89ab1..6ec3aabc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1914,21 +1914,22 @@ dependencies = [ [[package]] name = "casbin" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71063d3ee2f5ecc89229ccade0f3f8fb413b5e3978124a38b611216f91dd7c9" +checksum = "66e141a8db13c2e8bf3fdd6ac2b48ace7e70d2e4a66c329a4bb759e1368f22dc" dependencies = [ "async-trait", "fixedbitset", "getrandom 0.2.15", + "hashlink", "mini-moka", "once_cell", "parking_lot 0.12.3", "petgraph", "regex", "rhai", - "ritelinked", "serde", + "serde_json", "thiserror", "tokio", ] @@ -3720,15 +3721,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.8", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -6031,16 +6023,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ritelinked" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f2771d255fd99f0294f13249fecd0cae6e074f86b4197ec1f1689d537b44d3" -dependencies = [ - "ahash 0.7.8", - "hashbrown 0.11.2", -] - [[package]] name = "rkyv" version = "0.7.44" @@ -6478,9 +6460,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", diff --git a/libs/access-control/Cargo.toml b/libs/access-control/Cargo.toml index c008ce219..f77889c90 100644 --- a/libs/access-control/Cargo.toml +++ b/libs/access-control/Cargo.toml @@ -8,7 +8,7 @@ actix-http.workspace = true app-error.workspace = true anyhow.workspace = true async-trait.workspace = true -casbin = { version = "2.2.0", features = [ +casbin = { version = "2.5.0", features = [ "cached", "runtime-tokio", "incremental", diff --git a/libs/access-control/src/casbin/access.rs b/libs/access-control/src/casbin/access.rs index 000bec63e..838e8380a 100644 --- a/libs/access-control/src/casbin/access.rs +++ b/libs/access-control/src/casbin/access.rs @@ -6,7 +6,8 @@ use crate::metrics::{tick_metric, AccessControlMetrics}; use anyhow::anyhow; use app_error::AppError; -use casbin::rhai::ImmutableString; +use casbin::function_map::OperatorFunction; +use casbin::rhai::{Dynamic, ImmutableString}; use casbin::{CoreApi, DefaultModel, Enforcer, MgmtApi}; use database_entity::dto::{AFAccessLevel, AFRole}; @@ -52,10 +53,7 @@ impl AccessControl { let mut enforcer = casbin::Enforcer::new(model, adapter).await.map_err(|e| { AppError::Internal(anyhow!("Failed to create access control enforcer: {}", e)) })?; - enforcer.add_function( - "cmpRoleOrLevel", - |r: ImmutableString, p: ImmutableString| cmp_role_or_level(r.as_str(), p.as_str()), - ); + enforcer.add_function("cmpRoleOrLevel", OperatorFunction::Arg2(cmp_role_or_level)); let enforcer = Arc::new(AFEnforcer::new(enforcer, NoEnforceGroup).await?); tick_metric( @@ -198,29 +196,29 @@ pub async fn casbin_model() -> Result { /// * `r_act` - The role or access level from the request, prefixed with "r:" for roles or "l:" for levels. /// * `p_act` - The role or access level from the policy, prefixed with "r:" for roles or "l:" for levels. /// -pub fn cmp_role_or_level(r_act: &str, p_act: &str) -> bool { +pub fn cmp_role_or_level(r_act: ImmutableString, p_act: ImmutableString) -> Dynamic { trace!("cmp_role_or_level: r: {} p: {}", r_act, p_act); if r_act.starts_with("r:") && p_act.starts_with("r:") { - let r = AFRole::from_enforce_act(r_act); - let p = AFRole::from_enforce_act(p_act); - return p >= r; + let r = AFRole::from_enforce_act(r_act.as_str()); + let p = AFRole::from_enforce_act(p_act.as_str()); + return Dynamic::from_bool(p >= r); } if r_act.starts_with("l:") && p_act.starts_with("l:") { - let r = AFAccessLevel::from_enforce_act(r_act); - let p = AFAccessLevel::from_enforce_act(p_act); - return p >= r; + let r = AFAccessLevel::from_enforce_act(r_act.as_str()); + let p = AFAccessLevel::from_enforce_act(p_act.as_str()); + return Dynamic::from_bool(p >= r); } if r_act.starts_with("l:") && p_act.starts_with("r:") { - let r = AFAccessLevel::from_enforce_act(r_act); - let role = AFRole::from_enforce_act(p_act); + let r = AFAccessLevel::from_enforce_act(r_act.as_str()); + let role = AFRole::from_enforce_act(p_act.as_str()); let p = AFAccessLevel::from(&role); - return p >= r; + return Dynamic::from_bool(p >= r); } - false + Dynamic::from_bool(false) } /// Represents the entity stored at the index of the access control policy. diff --git a/libs/access-control/src/casbin/enforcer.rs b/libs/access-control/src/casbin/enforcer.rs index 3d63bfd44..93d652a83 100644 --- a/libs/access-control/src/casbin/enforcer.rs +++ b/libs/access-control/src/casbin/enforcer.rs @@ -244,7 +244,7 @@ mod tests { entity::ObjectType, }; use async_trait::async_trait; - use casbin::{prelude::*, rhai::ImmutableString}; + use casbin::{function_map::OperatorFunction, prelude::*}; use database_entity::dto::{AFAccessLevel, AFRole}; use super::{AFEnforcer, EnforcerGroup}; @@ -268,10 +268,7 @@ mod tests { .await .unwrap(); - enforcer.add_function( - "cmpRoleOrLevel", - |r: ImmutableString, p: ImmutableString| cmp_role_or_level(r.as_str(), p.as_str()), - ); + enforcer.add_function("cmpRoleOrLevel", OperatorFunction::Arg2(cmp_role_or_level)); AFEnforcer::new(enforcer, enforce_group).await.unwrap() } #[tokio::test] diff --git a/libs/database/Cargo.toml b/libs/database/Cargo.toml index 2367bf2ac..89b37ec9b 100644 --- a/libs/database/Cargo.toml +++ b/libs/database/Cargo.toml @@ -32,7 +32,11 @@ pgvector = { workspace = true, features = ["sqlx"] } tracing = { version = "0.1.40" } uuid = { workspace = true, features = ["serde", "v4"] } chrono = { version = "0.4", features = ["serde"] } -redis.workspace = true +redis = { workspace = true, features = [ + "aio", + "tokio-comp", + "connection-manager", +] } futures-util = "0.3.30" bytes = "1.5" aws-sdk-s3 = { version = "1.36.0", features = [