chore: remove collab ac cache (#420)
* chore: remove collab ac cache * chore: update member write workspace role * chore: fix test * chore: clippy
This commit is contained in:
parent
66a5033d16
commit
3e36dae50d
|
|
@ -23,6 +23,7 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
|
||||||
async fn update_policy(&self, uid: &i64, oid: &str, level: AFAccessLevel)
|
async fn update_policy(&self, uid: &i64, oid: &str, level: AFAccessLevel)
|
||||||
-> Result<(), AppError>;
|
-> Result<(), AppError>;
|
||||||
|
|
||||||
|
/// Removes the access level of the user for given collab object.
|
||||||
async fn enforce_read_collab(
|
async fn enforce_read_collab(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
|
|
@ -30,6 +31,7 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
|
||||||
oid: &str,
|
oid: &str,
|
||||||
) -> Result<bool, AppError>;
|
) -> Result<bool, AppError>;
|
||||||
|
|
||||||
|
/// Enforce the user's permission to write to the collab object.
|
||||||
async fn enforce_write_collab(
|
async fn enforce_write_collab(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
|
|
@ -37,15 +39,16 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
|
||||||
oid: &str,
|
oid: &str,
|
||||||
) -> Result<bool, AppError>;
|
) -> Result<bool, AppError>;
|
||||||
|
|
||||||
|
/// Enforce the user's permission to write to the workspace.
|
||||||
|
async fn enforce_write_workspace(&self, uid: &i64, workspace_id: &str) -> Result<bool, AppError>;
|
||||||
|
|
||||||
|
/// Enforce the user's permission to delete the collab object.
|
||||||
async fn enforce_delete(
|
async fn enforce_delete(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
uid: &i64,
|
uid: &i64,
|
||||||
oid: &str,
|
oid: &str,
|
||||||
) -> Result<bool, AppError>;
|
) -> Result<bool, AppError>;
|
||||||
|
|
||||||
/// Returns the role of the user in the workspace.
|
|
||||||
async fn enforce_write_workspace(&self, uid: &i64, workspace_id: &str) -> Result<bool, AppError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a storage mechanism for collaborations.
|
/// Represents a storage mechanism for collaborations.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use crate::biz::casbin::access_control::ObjectType;
|
use crate::biz::casbin::access_control::ObjectType;
|
||||||
use crate::biz::casbin::access_control::{
|
use crate::biz::casbin::access_control::{
|
||||||
enable_access_control, AccessControl, AccessControlChange, Action, ActionVariant,
|
enable_access_control, AccessControl, Action, ActionVariant,
|
||||||
};
|
};
|
||||||
use crate::biz::collab::access_control::CollabAccessControl;
|
use crate::biz::collab::access_control::CollabAccessControl;
|
||||||
use app_error::AppError;
|
use app_error::AppError;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use collab_rt::RealtimeAccessControl;
|
use collab_rt::RealtimeAccessControl;
|
||||||
use dashmap::DashMap;
|
|
||||||
use database_entity::dto::AFAccessLevel;
|
use database_entity::dto::AFAccessLevel;
|
||||||
use std::sync::Arc;
|
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -93,35 +93,25 @@ impl CollabAccessControl for CollabAccessControlImpl {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RealtimeCollabAccessControlImpl {
|
pub struct RealtimeCollabAccessControlImpl {
|
||||||
access_control: AccessControl,
|
access_control: AccessControl,
|
||||||
action_by_oid: Arc<DashMap<String, Action>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RealtimeCollabAccessControlImpl {
|
impl RealtimeCollabAccessControlImpl {
|
||||||
pub fn new(access_control: AccessControl) -> Self {
|
pub fn new(access_control: AccessControl) -> Self {
|
||||||
let action_by_oid = Arc::new(DashMap::new());
|
// let action_by_oid = Arc::new(DashMap::new());
|
||||||
let mut sub = access_control.subscribe_change();
|
// let mut sub = access_control.subscribe_change();
|
||||||
let weak_action_by_oid = Arc::downgrade(&action_by_oid);
|
// let weak_action_by_oid = Arc::downgrade(&action_by_oid);
|
||||||
|
// tokio::spawn(async move {
|
||||||
tokio::spawn(async move {
|
// while let Ok(change) = sub.recv().await {
|
||||||
while let Ok(change) = sub.recv().await {
|
// match weak_action_by_oid.upgrade() {
|
||||||
match weak_action_by_oid.upgrade() {
|
// None => break,
|
||||||
None => break,
|
// Some(action_by_oid) => match change {
|
||||||
Some(action_by_oid) => match change {
|
// AccessControlChange::UpdatePolicy { uid, oid } => {},
|
||||||
AccessControlChange::UpdatePolicy { uid, oid } => {
|
// AccessControlChange::RemovePolicy { uid, oid } => {},
|
||||||
action_by_oid.remove(&cache_key(uid, &oid));
|
// },
|
||||||
},
|
// }
|
||||||
AccessControlChange::RemovePolicy { uid, oid } => {
|
// }
|
||||||
action_by_oid.remove(&cache_key(uid, &oid));
|
// });
|
||||||
},
|
Self { access_control }
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
access_control,
|
|
||||||
action_by_oid,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn can_perform_action(
|
async fn can_perform_action(
|
||||||
|
|
@ -132,13 +122,6 @@ impl RealtimeCollabAccessControlImpl {
|
||||||
required_action: Action,
|
required_action: Action,
|
||||||
) -> Result<bool, AppError> {
|
) -> Result<bool, AppError> {
|
||||||
if enable_access_control() {
|
if enable_access_control() {
|
||||||
let key = cache_key(*uid, oid);
|
|
||||||
// Check if the action is already cached
|
|
||||||
if let Some(action) = self.action_by_oid.get(&key) {
|
|
||||||
return Ok(*action >= required_action);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not in cache, enforce access control
|
|
||||||
let is_permitted = self
|
let is_permitted = self
|
||||||
.access_control
|
.access_control
|
||||||
.enforce(
|
.enforce(
|
||||||
|
|
@ -149,11 +132,6 @@ impl RealtimeCollabAccessControlImpl {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if is_permitted {
|
|
||||||
// Permission granted, cache the action
|
|
||||||
self.action_by_oid.insert(key, required_action);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(is_permitted)
|
Ok(is_permitted)
|
||||||
} else {
|
} else {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|
@ -161,11 +139,6 @@ impl RealtimeCollabAccessControlImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn cache_key(uid: i64, oid: &str) -> String {
|
|
||||||
format!("{}:{}", uid, oid)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl RealtimeAccessControl for RealtimeCollabAccessControlImpl {
|
impl RealtimeAccessControl for RealtimeCollabAccessControlImpl {
|
||||||
async fn can_write_collab(
|
async fn can_write_collab(
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use actix_web::http::Method;
|
||||||
use app_error::AppError;
|
use app_error::AppError;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use database::collab::CollabStorageAccessControl;
|
use database::collab::CollabStorageAccessControl;
|
||||||
use database_entity::dto::{AFAccessLevel, AFRole};
|
use database_entity::dto::AFAccessLevel;
|
||||||
|
|
||||||
use crate::biz::collab::cache::CollabCache;
|
use crate::biz::collab::cache::CollabCache;
|
||||||
|
|
||||||
|
|
@ -218,6 +218,13 @@ where
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn enforce_write_workspace(&self, uid: &i64, workspace_id: &str) -> Result<bool, AppError> {
|
||||||
|
self
|
||||||
|
.workspace_access_control
|
||||||
|
.enforce_action(uid, workspace_id, Action::Write)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn enforce_delete(
|
async fn enforce_delete(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
|
|
@ -229,11 +236,4 @@ where
|
||||||
.enforce_access_level(workspace_id, uid, oid, AFAccessLevel::FullAccess)
|
.enforce_access_level(workspace_id, uid, oid, AFAccessLevel::FullAccess)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enforce_write_workspace(&self, uid: &i64, workspace_id: &str) -> Result<bool, AppError> {
|
|
||||||
self
|
|
||||||
.workspace_access_control
|
|
||||||
.enforce_role(uid, workspace_id, AFRole::Owner)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,6 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, params), oid = %params.oid, err)]
|
#[instrument(level = "trace", skip(self, params), oid = %params.oid, err)]
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
|
||||||
async fn insert_or_update_collab_with_transaction(
|
async fn insert_or_update_collab_with_transaction(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
|
|
@ -188,6 +187,11 @@ where
|
||||||
// When the collab is not exist in the database, and the user passes the permission check,
|
// When the collab is not exist in the database, and the user passes the permission check,
|
||||||
// which means the user has the permission to create the collab, we should update the policy
|
// which means the user has the permission to create the collab, we should update the policy
|
||||||
if !is_collab_exist_in_db {
|
if !is_collab_exist_in_db {
|
||||||
|
trace!(
|
||||||
|
"Update policy for user:{} to create collab:{}",
|
||||||
|
uid,
|
||||||
|
params.object_id
|
||||||
|
);
|
||||||
self
|
self
|
||||||
.access_control
|
.access_control
|
||||||
.update_policy(uid, ¶ms.object_id, AFAccessLevel::FullAccess)
|
.update_policy(uid, ¶ms.object_id, AFAccessLevel::FullAccess)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue