mirror of
https://github.com/AppFlowy-IO/AppFlowy-Cloud.git
synced 2025-04-19 03:24:42 -04:00
feat: add role for user when querying workspaces (#983)
This commit is contained in:
parent
288fd59d3b
commit
85452ddfab
8 changed files with 138 additions and 20 deletions
29
.sqlx/query-aa75996ca6aa12f0bcaa5fb092ac279f8a94aadcc29d0e2b652dc420506835e7.json
generated
Normal file
29
.sqlx/query-aa75996ca6aa12f0bcaa5fb092ac279f8a94aadcc29d0e2b652dc420506835e7.json
generated
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT workspace_id, role_id\n FROM af_workspace_member\n WHERE workspace_id = ANY($1)\n AND uid = (SELECT uid FROM public.af_user WHERE uuid = $2)\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "workspace_id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "role_id",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "aa75996ca6aa12f0bcaa5fb092ac279f8a94aadcc29d0e2b652dc420506835e7"
|
||||
}
|
|
@ -624,6 +624,8 @@ pub struct AFWorkspace {
|
|||
pub created_at: DateTime<Utc>,
|
||||
pub icon: String,
|
||||
pub member_count: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub role: Option<AFRole>, // role of the user requesting the workspace
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
|
|
@ -53,6 +53,7 @@ impl TryFrom<AFWorkspaceRow> for AFWorkspace {
|
|||
created_at,
|
||||
icon,
|
||||
member_count: None,
|
||||
role: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +99,7 @@ impl TryFrom<AFWorkspaceWithMemberCountRow> for AFWorkspace {
|
|||
created_at,
|
||||
icon,
|
||||
member_count: Some(value.member_count),
|
||||
role: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -851,10 +851,32 @@ pub async fn select_member_count_for_workspaces<'a, E: Executor<'a, Database = P
|
|||
};
|
||||
ret.insert(row.workspace_id, count);
|
||||
}
|
||||
for workspace_id in workspace_ids.iter() {
|
||||
if !ret.contains_key(workspace_id) {
|
||||
ret.insert(*workspace_id, 0);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub async fn select_roles_for_workspaces(
|
||||
pg_pool: &PgPool,
|
||||
user_uuid: &Uuid,
|
||||
workspace_ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, AFRole>, AppError> {
|
||||
let query_res = sqlx::query!(
|
||||
r#"
|
||||
SELECT workspace_id, role_id
|
||||
FROM af_workspace_member
|
||||
WHERE workspace_id = ANY($1)
|
||||
AND uid = (SELECT uid FROM public.af_user WHERE uuid = $2)
|
||||
"#,
|
||||
workspace_ids,
|
||||
user_uuid,
|
||||
)
|
||||
.fetch_all(pg_pool)
|
||||
.await?;
|
||||
|
||||
let mut ret = HashMap::with_capacity(workspace_ids.len());
|
||||
for row in query_res {
|
||||
let role = AFRole::from(row.role_id);
|
||||
ret.insert(row.workspace_id, role);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
|
|
|
@ -261,6 +261,7 @@ impl Default for ViewLayout {
|
|||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
pub struct QueryWorkspaceParam {
|
||||
pub include_member_count: Option<bool>,
|
||||
pub include_role: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
|
|
|
@ -338,10 +338,16 @@ async fn list_workspace_handler(
|
|||
state: Data<AppState>,
|
||||
query: web::Query<QueryWorkspaceParam>,
|
||||
) -> Result<JsonAppResponse<Vec<AFWorkspace>>> {
|
||||
let QueryWorkspaceParam {
|
||||
include_member_count,
|
||||
include_role,
|
||||
} = query.into_inner();
|
||||
|
||||
let workspaces = workspace::ops::get_all_user_workspaces(
|
||||
&state.pg_pool,
|
||||
&uuid,
|
||||
query.into_inner().include_member_count.unwrap_or(false),
|
||||
include_member_count.unwrap_or(false),
|
||||
include_role.unwrap_or(false),
|
||||
)
|
||||
.await?;
|
||||
Ok(AppResponse::Ok().with_data(workspaces).into())
|
||||
|
|
|
@ -256,6 +256,7 @@ pub async fn get_all_user_workspaces(
|
|||
pg_pool: &PgPool,
|
||||
user_uuid: &Uuid,
|
||||
include_member_count: bool,
|
||||
include_role: bool,
|
||||
) -> Result<Vec<AFWorkspace>, AppResponseError> {
|
||||
let workspaces = select_all_user_workspaces(pg_pool, user_uuid).await?;
|
||||
let mut workspaces = workspaces
|
||||
|
@ -273,10 +274,23 @@ pub async fn get_all_user_workspaces(
|
|||
.iter()
|
||||
.map(|row| row.workspace_id)
|
||||
.collect::<Vec<_>>();
|
||||
let member_count_by_workspace_id = select_member_count_for_workspaces(pg_pool, &ids).await?;
|
||||
let mut member_count_by_workspace_id =
|
||||
select_member_count_for_workspaces(pg_pool, &ids).await?;
|
||||
for workspace in workspaces.iter_mut() {
|
||||
if let Some(member_count) = member_count_by_workspace_id.get(&workspace.workspace_id) {
|
||||
workspace.member_count = Some(*member_count);
|
||||
if let Some(member_count) = member_count_by_workspace_id.remove(&workspace.workspace_id) {
|
||||
workspace.member_count = Some(member_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
if include_role {
|
||||
let ids = workspaces
|
||||
.iter()
|
||||
.map(|row| row.workspace_id)
|
||||
.collect::<Vec<_>>();
|
||||
let mut roles_by_workspace_id = select_roles_for_workspaces(pg_pool, user_uuid, &ids).await?;
|
||||
for workspace in workspaces.iter_mut() {
|
||||
if let Some(role) = roles_by_workspace_id.remove(&workspace.workspace_id) {
|
||||
workspace.role = Some(role.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,15 @@ async fn invite_workspace_crud() {
|
|||
.workspace_id;
|
||||
|
||||
let (bob_client, bob) = generate_unique_registered_user_client().await;
|
||||
let bob_workspace_id = bob_client
|
||||
.get_workspaces()
|
||||
.await
|
||||
.unwrap()
|
||||
.first()
|
||||
.unwrap()
|
||||
.workspace_id;
|
||||
|
||||
// alice invite bob to alice's workspace
|
||||
alice_client
|
||||
.invite_workspace_members(
|
||||
alice_workspace_id.to_string().as_str(),
|
||||
|
@ -94,16 +103,49 @@ async fn invite_workspace_crud() {
|
|||
.unwrap();
|
||||
assert_eq!(accepted_invs.len(), 1);
|
||||
|
||||
// workspace now have 2 members
|
||||
let member_count = alice_client
|
||||
.get_workspaces_opt(QueryWorkspaceParam {
|
||||
include_member_count: Some(true),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.first()
|
||||
.unwrap()
|
||||
.member_count
|
||||
.unwrap();
|
||||
assert_eq!(member_count, 2);
|
||||
{
|
||||
// alice's view of the workspaces
|
||||
let workspaces = alice_client
|
||||
.get_workspaces_opt(QueryWorkspaceParam {
|
||||
include_member_count: Some(true),
|
||||
include_role: Some(true),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(workspaces.len(), 1);
|
||||
assert_eq!(workspaces[0].workspace_id, alice_workspace_id);
|
||||
assert_eq!(workspaces[0].member_count, Some(2));
|
||||
assert_eq!(workspaces[0].role, Some(AFRole::Owner));
|
||||
}
|
||||
|
||||
{
|
||||
// bob's view of the workspaces
|
||||
// bob should see 2 workspaces, one is his own and the other is alice's
|
||||
let workspaces = bob_client
|
||||
.get_workspaces_opt(QueryWorkspaceParam {
|
||||
include_member_count: Some(true),
|
||||
include_role: Some(true),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(workspaces.len(), 2);
|
||||
{
|
||||
let alice_workspace = workspaces
|
||||
.iter()
|
||||
.find(|w| w.workspace_id == alice_workspace_id)
|
||||
.unwrap();
|
||||
assert_eq!(alice_workspace.member_count, Some(2));
|
||||
assert_eq!(alice_workspace.role, Some(AFRole::Member));
|
||||
}
|
||||
{
|
||||
let bob_workspace = workspaces
|
||||
.iter()
|
||||
.find(|w| w.workspace_id == bob_workspace_id)
|
||||
.unwrap();
|
||||
println!("{:?}", bob_workspace);
|
||||
assert_eq!(bob_workspace.member_count, Some(1));
|
||||
assert_eq!(bob_workspace.role, Some(AFRole::Owner));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue