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:
Nathan.fooo 2024-03-26 21:36:24 +08:00 committed by GitHub
parent 66a5033d16
commit 3e36dae50d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 57 deletions

View File

@ -23,6 +23,7 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
async fn update_policy(&self, uid: &i64, oid: &str, level: AFAccessLevel)
-> Result<(), AppError>;
/// Removes the access level of the user for given collab object.
async fn enforce_read_collab(
&self,
workspace_id: &str,
@ -30,6 +31,7 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
oid: &str,
) -> Result<bool, AppError>;
/// Enforce the user's permission to write to the collab object.
async fn enforce_write_collab(
&self,
workspace_id: &str,
@ -37,15 +39,16 @@ pub trait CollabStorageAccessControl: Send + Sync + 'static {
oid: &str,
) -> 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(
&self,
workspace_id: &str,
uid: &i64,
oid: &str,
) -> 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.

View File

@ -1,15 +1,15 @@
use crate::biz::casbin::access_control::ObjectType;
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 app_error::AppError;
use async_trait::async_trait;
use collab_rt::RealtimeAccessControl;
use dashmap::DashMap;
use database_entity::dto::AFAccessLevel;
use std::sync::Arc;
use tracing::instrument;
#[derive(Clone)]
@ -93,35 +93,25 @@ impl CollabAccessControl for CollabAccessControlImpl {
#[derive(Clone)]
pub struct RealtimeCollabAccessControlImpl {
access_control: AccessControl,
action_by_oid: Arc<DashMap<String, Action>>,
}
impl RealtimeCollabAccessControlImpl {
pub fn new(access_control: AccessControl) -> Self {
let action_by_oid = Arc::new(DashMap::new());
let mut sub = access_control.subscribe_change();
let weak_action_by_oid = Arc::downgrade(&action_by_oid);
tokio::spawn(async move {
while let Ok(change) = sub.recv().await {
match weak_action_by_oid.upgrade() {
None => break,
Some(action_by_oid) => match change {
AccessControlChange::UpdatePolicy { 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,
action_by_oid,
}
// let action_by_oid = Arc::new(DashMap::new());
// let mut sub = access_control.subscribe_change();
// let weak_action_by_oid = Arc::downgrade(&action_by_oid);
// tokio::spawn(async move {
// while let Ok(change) = sub.recv().await {
// match weak_action_by_oid.upgrade() {
// None => break,
// Some(action_by_oid) => match change {
// AccessControlChange::UpdatePolicy { uid, oid } => {},
// AccessControlChange::RemovePolicy { uid, oid } => {},
// },
// }
// }
// });
Self { access_control }
}
async fn can_perform_action(
@ -132,13 +122,6 @@ impl RealtimeCollabAccessControlImpl {
required_action: Action,
) -> Result<bool, AppError> {
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
.access_control
.enforce(
@ -149,11 +132,6 @@ impl RealtimeCollabAccessControlImpl {
)
.await?;
if is_permitted {
// Permission granted, cache the action
self.action_by_oid.insert(key, required_action);
}
Ok(is_permitted)
} else {
Ok(true)
@ -161,11 +139,6 @@ impl RealtimeCollabAccessControlImpl {
}
}
#[inline]
fn cache_key(uid: i64, oid: &str) -> String {
format!("{}:{}", uid, oid)
}
#[async_trait]
impl RealtimeAccessControl for RealtimeCollabAccessControlImpl {
async fn can_write_collab(

View File

@ -7,7 +7,7 @@ use actix_web::http::Method;
use app_error::AppError;
use async_trait::async_trait;
use database::collab::CollabStorageAccessControl;
use database_entity::dto::{AFAccessLevel, AFRole};
use database_entity::dto::AFAccessLevel;
use crate::biz::collab::cache::CollabCache;
@ -218,6 +218,13 @@ where
.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(
&self,
workspace_id: &str,
@ -229,11 +236,4 @@ where
.enforce_access_level(workspace_id, uid, oid, AFAccessLevel::FullAccess)
.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
}
}

View File

@ -172,7 +172,6 @@ where
}
#[instrument(level = "trace", skip(self, params), oid = %params.oid, err)]
#[allow(clippy::blocks_in_if_conditions)]
async fn insert_or_update_collab_with_transaction(
&self,
workspace_id: &str,
@ -188,6 +187,11 @@ where
// 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
if !is_collab_exist_in_db {
trace!(
"Update policy for user:{} to create collab:{}",
uid,
params.object_id
);
self
.access_control
.update_policy(uid, &params.object_id, AFAccessLevel::FullAccess)