diff --git a/.sqlx/query-19fd96e0183b93b1751440a2562624f2ffc9c958ed3d06b26162eb1c249c62e9.json b/.sqlx/query-19fd96e0183b93b1751440a2562624f2ffc9c958ed3d06b26162eb1c249c62e9.json new file mode 100644 index 00000000..94bb8dc1 --- /dev/null +++ b/.sqlx/query-19fd96e0183b93b1751440a2562624f2ffc9c958ed3d06b26162eb1c249c62e9.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO af_collab_member (uid, oid, permission_id)\n VALUES ($1, $2, $3)\n ON CONFLICT (uid, oid)\n DO UPDATE\n SET permission_id = excluded.permission_id;\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Text", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "19fd96e0183b93b1751440a2562624f2ffc9c958ed3d06b26162eb1c249c62e9" +} diff --git a/.sqlx/query-42d345fbdc25ad7b36d35515079e00e018e4f58a9a4ac4efbfa4768cadcc6c85.json b/.sqlx/query-42d345fbdc25ad7b36d35515079e00e018e4f58a9a4ac4efbfa4768cadcc6c85.json deleted file mode 100644 index a612cd44..00000000 --- a/.sqlx/query-42d345fbdc25ad7b36d35515079e00e018e4f58a9a4ac4efbfa4768cadcc6c85.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT rp.permission_id \n FROM af_role_permissions rp\n JOIN af_roles ON rp.role_id = af_roles.id\n WHERE af_roles.name = 'Owner';\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "permission_id", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false - ] - }, - "hash": "42d345fbdc25ad7b36d35515079e00e018e4f58a9a4ac4efbfa4768cadcc6c85" -} diff --git a/.sqlx/query-8135c6a16c27a0ccbde65473a8041007ae9ef7f546fadb656a2948ffb0db8e53.json b/.sqlx/query-8135c6a16c27a0ccbde65473a8041007ae9ef7f546fadb656a2948ffb0db8e53.json deleted file mode 100644 index 1d4ff7b8..00000000 --- a/.sqlx/query-8135c6a16c27a0ccbde65473a8041007ae9ef7f546fadb656a2948ffb0db8e53.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT DISTINCT af_collab_member.oid FROM af_collab_member", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "oid", - "type_info": "Text" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false - ] - }, - "hash": "8135c6a16c27a0ccbde65473a8041007ae9ef7f546fadb656a2948ffb0db8e53" -} diff --git a/.sqlx/query-9eba47895808e9968529d789a02758807486054028990fffef62fb89ac047750.json b/.sqlx/query-9eba47895808e9968529d789a02758807486054028990fffef62fb89ac047750.json new file mode 100644 index 00000000..0f51b573 --- /dev/null +++ b/.sqlx/query-9eba47895808e9968529d789a02758807486054028990fffef62fb89ac047750.json @@ -0,0 +1,32 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n uid, oid, access_level\n FROM af_collab_member\n INNER JOIN af_permissions\n ON af_collab_member.permission_id = af_permissions.id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "uid", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "oid", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "access_level", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "9eba47895808e9968529d789a02758807486054028990fffef62fb89ac047750" +} diff --git a/.sqlx/query-c5ba2a6febad1655b75eecad9d088694a6f0f93a84c32a0228a7cfd1a6f063f1.json b/.sqlx/query-c5ba2a6febad1655b75eecad9d088694a6f0f93a84c32a0228a7cfd1a6f063f1.json deleted file mode 100644 index 4eacae1d..00000000 --- a/.sqlx/query-c5ba2a6febad1655b75eecad9d088694a6f0f93a84c32a0228a7cfd1a6f063f1.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": " \n INSERT INTO af_collab_member (uid, oid, permission_id)\n VALUES ($1, $2, $3)\n ON CONFLICT (uid, oid)\n DO UPDATE\n SET permission_id = excluded.permission_id;\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Text", - "Int4" - ] - }, - "nullable": [] - }, - "hash": "c5ba2a6febad1655b75eecad9d088694a6f0f93a84c32a0228a7cfd1a6f063f1" -} diff --git a/.sqlx/query-d6708c221831093b03524bd6b73974f6f41db00b5f58f47ad7180d068e273406.json b/.sqlx/query-d6708c221831093b03524bd6b73974f6f41db00b5f58f47ad7180d068e273406.json new file mode 100644 index 00000000..574d0fe4 --- /dev/null +++ b/.sqlx/query-d6708c221831093b03524bd6b73974f6f41db00b5f58f47ad7180d068e273406.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT rp.permission_id\n FROM af_role_permissions rp\n JOIN af_roles ON rp.role_id = af_roles.id\n WHERE af_roles.name = 'Owner';\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "permission_id", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false + ] + }, + "hash": "d6708c221831093b03524bd6b73974f6f41db00b5f58f47ad7180d068e273406" +} diff --git a/libs/database-entity/src/pg_row.rs b/libs/database-entity/src/pg_row.rs index e9f7bb91..c0a7b9b6 100644 --- a/libs/database-entity/src/pg_row.rs +++ b/libs/database-entity/src/pg_row.rs @@ -62,6 +62,13 @@ pub struct AFWorkspaceMemberRow { pub role: AFRole, } +#[derive(FromRow)] +pub struct AFCollabMemerAccessLevelRow { + pub uid: i64, + pub oid: String, + pub access_level: AFAccessLevel, +} + #[derive(FromRow, Clone, Debug, Serialize, Deserialize)] pub struct AFCollabMemberRow { pub uid: i64, diff --git a/libs/database/src/collab/collab_db_ops.rs b/libs/database/src/collab/collab_db_ops.rs index b3311670..43a82a16 100644 --- a/libs/database/src/collab/collab_db_ops.rs +++ b/libs/database/src/collab/collab_db_ops.rs @@ -5,7 +5,10 @@ use database_entity::dto::{ BatchQueryCollab, InsertCollabParams, QueryCollabResult, RawData, }; +use database_entity::pg_row::AFCollabMemerAccessLevelRow; + use app_error::AppError; +use futures_util::stream::BoxStream; use sqlx::postgres::PgRow; use sqlx::{Error, Executor, PgPool, Postgres, Row, Transaction}; use std::collections::HashMap; @@ -101,7 +104,7 @@ pub async fn insert_into_af_collab( // Get the permission_id of the Owner let permission_id: i32 = sqlx::query_scalar!( r#" - SELECT rp.permission_id + SELECT rp.permission_id FROM af_role_permissions rp JOIN af_roles ON rp.role_id = af_roles.id WHERE af_roles.name = 'Owner'; @@ -340,7 +343,7 @@ pub async fn upsert_collab_member_with_txn + Debug>( .context("Get permission id from access level fail")?; sqlx::query!( - r#" + r#" INSERT INTO af_collab_member (uid, oid, permission_id) VALUES ($1, $2, $3) ON CONFLICT (uid, oid) @@ -382,24 +385,20 @@ pub async fn delete_collab_member(uid: i64, oid: &str, pg_pool: &PgPool) -> Resu Ok(()) } -#[instrument(level = "info", skip_all, err)] -pub async fn select_all_collab_members( +pub fn select_collab_member_access_level( pg_pool: &PgPool, -) -> Result)>, AppError> { - let collabs: Vec<_> = sqlx::query!("SELECT DISTINCT af_collab_member.oid FROM af_collab_member") - .fetch_all(pg_pool) - .await? - .into_iter() - .map(|r| r.oid) - .collect(); - - let mut collab_members = Vec::with_capacity(collabs.len()); - for oid in collabs { - let members = select_collab_members(&oid, pg_pool).await?; - collab_members.push((oid, members)); - } - - Ok(collab_members) +) -> BoxStream<'_, sqlx::Result> { + sqlx::query_as!( + AFCollabMemerAccessLevelRow, + r#" + SELECT + uid, oid, access_level + FROM af_collab_member + INNER JOIN af_permissions + ON af_collab_member.permission_id = af_permissions.id + "# + ) + .fetch(pg_pool) } #[inline] diff --git a/libs/database/src/workspace.rs b/libs/database/src/workspace.rs index 4b5aa0ad..4d9d92ee 100644 --- a/libs/database/src/workspace.rs +++ b/libs/database/src/workspace.rs @@ -242,13 +242,12 @@ pub async fn delete_workspace_members( pub fn select_workspace_member_perm_stream( pg_pool: &PgPool, -) -> Result>, AppError> { - let stream = sqlx::query_as!( +) -> BoxStream<'_, sqlx::Result> { + sqlx::query_as!( AFWorkspaceMemberPermRow, "SELECT uid, role_id as role, workspace_id FROM af_workspace_member" ) - .fetch(pg_pool); - Ok(stream) + .fetch(pg_pool) } /// returns a list of workspace members, sorted by their creation time. diff --git a/src/biz/casbin/adapter.rs b/src/biz/casbin/adapter.rs index 8500e40b..96177102 100644 --- a/src/biz/casbin/adapter.rs +++ b/src/biz/casbin/adapter.rs @@ -5,10 +5,10 @@ use casbin::Adapter; use casbin::Filter; use casbin::Model; use casbin::Result; -use database::collab::select_all_collab_members; +use database::collab::select_collab_member_access_level; use database::workspace::select_workspace_member_perm_stream; use database_entity::dto::AFAccessLevel; -use database_entity::dto::AFCollabMember; +use database_entity::pg_row::AFCollabMemerAccessLevelRow; use database_entity::pg_row::AFWorkspaceMemberPermRow; use futures_util::stream::BoxStream; use sqlx::PgPool; @@ -26,21 +26,23 @@ impl PgAdapter { } } -fn create_collab_policies(collab_members: Vec<(String, Vec)>) -> Vec> { +async fn create_collab_policies( + mut stream: BoxStream<'_, sqlx::Result>, +) -> Result>> { let mut policies: Vec> = Vec::new(); - for (oid, members) in collab_members { - for m in members { - let p = [ - m.uid.to_string(), - ObjectType::Collab(&oid).to_string(), - i32::from(m.permission.access_level).to_string(), - ] - .to_vec(); - policies.push(p); - } + + while let Some(result) = stream.next().await { + let member_access_lv = result.map_err(|err| AdapterError(Box::new(err)))?; + let policy = [ + member_access_lv.uid.to_string(), + ObjectType::Collab(&member_access_lv.oid).to_string(), + i32::from(member_access_lv.access_level).to_string(), + ] + .to_vec(); + policies.push(policy); } - policies + Ok(policies) } async fn create_workspace_policies( @@ -65,18 +67,15 @@ async fn create_workspace_policies( #[async_trait] impl Adapter for PgAdapter { async fn load_policy(&mut self, model: &mut dyn Model) -> Result<()> { - let workspace_member_perm_stream = select_workspace_member_perm_stream(&self.pg_pool) - .map_err(|err| AdapterError(Box::new(err)))?; + let workspace_member_perm_stream = select_workspace_member_perm_stream(&self.pg_pool); let workspace_policies = create_workspace_policies(workspace_member_perm_stream).await?; // Policy definition `p` of type `p`. See `model.conf` model.add_policies("p", "p", workspace_policies); - let collab_members = select_all_collab_members(&self.pg_pool) - .await - .map_err(|err| AdapterError(Box::new(err)))?; + let collab_member_access_lv_stream = select_collab_member_access_level(&self.pg_pool); + let collab_policies = create_collab_policies(collab_member_access_lv_stream).await?; - let collab_policies = create_collab_policies(collab_members); // Policy definition `p` of type `p`. See `model.conf` model.add_policies("p", "p", collab_policies);