AppFlowy-Cloud/services/appflowy-collaborate/src/collab/notification.rs

95 lines
2.8 KiB
Rust

use access_control::access::{AccessControl, ObjectType};
use access_control::act::ActionVariant;
use database::pg_row::AFCollabMemberRow;
use database::workspace::select_permission;
use serde::Deserialize;
use sqlx::PgPool;
use tokio::sync::broadcast;
use tracing::error;
use tracing::log::warn;
#[allow(dead_code)]
pub fn spawn_listen_on_collab_member_change(
pg_pool: PgPool,
mut listener: broadcast::Receiver<CollabMemberNotification>,
access_control: AccessControl,
) {
tokio::spawn(async move {
while let Ok(change) = listener.recv().await {
match change.action_type {
CollabMemberAction::INSERT | CollabMemberAction::UPDATE => {
if let Some(member_row) = change.new {
let permission_row = select_permission(&pg_pool, &member_row.permission_id).await;
if let Ok(Some(row)) = permission_row {
if let Err(err) = access_control
.update_policy(
&member_row.uid,
ObjectType::Collab(&member_row.oid),
ActionVariant::FromAccessLevel(&row.access_level),
)
.await
{
error!(
"Failed to update the user:{} collab{} access control, error: {}",
member_row.uid, member_row.oid, err
);
}
}
} else {
error!("The new collab member is None")
}
},
CollabMemberAction::DELETE => {
if let (Some(oid), Some(uid)) = (change.old_oid(), change.old_uid()) {
if let Err(err) = access_control
.remove_policy(uid, &ObjectType::Collab(oid))
.await
{
warn!(
"Failed to remove the user:{} collab{} access control, error: {}",
uid, oid, err
);
}
} else {
warn!("The oid or uid is None")
}
},
}
}
});
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Deserialize, Clone, Debug)]
pub enum CollabMemberAction {
INSERT,
UPDATE,
DELETE,
}
#[derive(Deserialize, Debug, Clone)]
pub struct CollabMemberNotification {
/// The old will be None if the row does not exist before
pub old: Option<AFCollabMemberRow>,
/// The new will be None if the row is deleted
pub new: Option<AFCollabMemberRow>,
/// Represent the action of the database. Such as INSERT, UPDATE, DELETE
pub action_type: CollabMemberAction,
}
impl CollabMemberNotification {
pub fn old_uid(&self) -> Option<&i64> {
self.old.as_ref().map(|o| &o.uid)
}
pub fn old_oid(&self) -> Option<&str> {
self.old.as_ref().map(|o| o.oid.as_str())
}
pub fn new_uid(&self) -> Option<&i64> {
self.new.as_ref().map(|n| &n.uid)
}
pub fn new_oid(&self) -> Option<&str> {
self.new.as_ref().map(|n| n.oid.as_str())
}
}