AppFlowy-Cloud/tests/casbin/user_ac_test.rs

271 lines
7.9 KiB
Rust

use crate::casbin::*;
use anyhow::anyhow;
use appflowy_cloud::biz;
use appflowy_cloud::biz::casbin::adapter::PgAdapter;
use appflowy_cloud::biz::casbin::{Action, ObjectType};
use casbin::{CoreApi, DefaultModel, Enforcer};
use database_entity::dto::{AFAccessLevel, AFRole};
use shared_entity::dto::workspace_dto::CreateWorkspaceMember;
use sqlx::PgPool;
#[sqlx::test(migrations = false)]
async fn test_create_user(pool: PgPool) -> anyhow::Result<()> {
setup_db(&pool).await?;
let user = create_user(&pool).await?;
// Get workspace details
let workspace = database::workspace::select_user_workspace(&pool, &user.uuid)
.await?
.into_iter()
.next()
.ok_or(anyhow!("workspace should be created"))?;
let model = DefaultModel::from_str(MODEL_CONF).await?;
let enforcer = Enforcer::new(model, PgAdapter::new(pool.clone())).await?;
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Workspace(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFRole::Owner).to_string(),
))
.context("user should be owner of its workspace")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::FullAccess).to_string(),
))
.context("user should have full access of its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Read.to_string(),
))
.context("user should be able to read its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Write.to_string(),
))
.context("user should be able to write its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Delete.to_string(),
))
.context("user should be able to delete its collab")?);
Ok(())
}
#[sqlx::test(migrations = false)]
async fn test_add_users_to_workspace(pool: PgPool) -> anyhow::Result<()> {
setup_db(&pool).await?;
let user_main = create_user(&pool).await?;
let user_owner = create_user(&pool).await?;
let user_member = create_user(&pool).await?;
let user_guest = create_user(&pool).await?;
// Get workspace details
let workspace = database::workspace::select_user_workspace(&pool, &user_main.uuid)
.await?
.into_iter()
.next()
.ok_or(anyhow!("workspace should be created"))?;
let members = vec![
CreateWorkspaceMember {
email: user_owner.email.clone(),
role: AFRole::Owner,
},
CreateWorkspaceMember {
email: user_member.email.clone(),
role: AFRole::Member,
},
CreateWorkspaceMember {
email: user_guest.email.clone(),
role: AFRole::Guest,
},
];
let _ = biz::workspace::ops::add_workspace_members(
&pool,
&user_main.uuid,
&workspace.workspace_id,
members,
)
.await
.context("adding users to workspace")?;
let model = DefaultModel::from_str(MODEL_CONF).await?;
let enforcer = Enforcer::new(model, PgAdapter::new(pool.clone())).await?;
{
// Owner
let user = user_owner;
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::FullAccess).to_string(),
))
.context("owner should have full access of its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Read.to_string(),
))
.context("user should be able to read its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Write.to_string(),
))
.context("user should be able to write its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Delete.to_string(),
))
.context("user should be able to delete its collab")?);
}
{
// Member
let user = user_member;
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::ReadAndWrite).to_string(),
))
.context("member should have read write access of its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Read.to_string(),
))
.context("user should be able to read its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Write.to_string(),
))
.context("user should be able to write its collab")?);
assert!(!enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Delete.to_string(),
))
.context("user should not be able to delete its collab")?);
}
{
// Guest
let user = user_guest;
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::ReadOnly).to_string(),
))
.context("guest should have read only access of its collab")?);
assert!(enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Read.to_string(),
))
.context("user should not be able to read its collab")?);
assert!(!enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Write.to_string(),
))
.context("user should not be able to write its collab")?);
assert!(!enforcer
.enforce((
user.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
Action::Delete.to_string(),
))
.context("user should not be able to delete its collab")?);
}
Ok(())
}
#[sqlx::test(migrations = false)]
async fn test_reload_policy_after_adding_user_to_workspace(pool: PgPool) -> anyhow::Result<()> {
setup_db(&pool).await?;
let user_owner = create_user(&pool).await?;
let user_member = create_user(&pool).await?;
// Get workspace details
let workspace = database::workspace::select_user_workspace(&pool, &user_owner.uuid)
.await?
.into_iter()
.next()
.ok_or(anyhow!("workspace should be created"))?;
// Create enforcer before adding user to workspace
let model = DefaultModel::from_str(MODEL_CONF).await?;
let mut enforcer = Enforcer::new(model, PgAdapter::new(pool.clone())).await?;
let members = vec![CreateWorkspaceMember {
email: user_member.email.clone(),
role: AFRole::Member,
}];
let _ = biz::workspace::ops::add_workspace_members(
&pool,
&user_owner.uuid,
&workspace.workspace_id,
members,
)
.await
.context("adding users to workspace")?;
assert!(!enforcer
.enforce((
user_member.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::ReadAndWrite).to_string(),
))
.context("member should not have read write access to collab before reload")?);
enforcer.load_policy().await?;
assert!(enforcer
.enforce((
user_member.uid.to_string(),
ObjectType::Collab(&workspace.workspace_id.to_string()).to_string(),
i32::from(AFAccessLevel::ReadAndWrite).to_string(),
))
.context("member should have read write access to collab")?);
Ok(())
}