feat: add role for user when querying workspaces (#983)
This commit is contained in:
parent
288fd59d3b
commit
85452ddfab
|
|
@ -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 created_at: DateTime<Utc>,
|
||||||
pub icon: String,
|
pub icon: String,
|
||||||
pub member_count: Option<i64>,
|
pub member_count: Option<i64>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub role: Option<AFRole>, // role of the user requesting the workspace
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ impl TryFrom<AFWorkspaceRow> for AFWorkspace {
|
||||||
created_at,
|
created_at,
|
||||||
icon,
|
icon,
|
||||||
member_count: None,
|
member_count: None,
|
||||||
|
role: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,6 +99,7 @@ impl TryFrom<AFWorkspaceWithMemberCountRow> for AFWorkspace {
|
||||||
created_at,
|
created_at,
|
||||||
icon,
|
icon,
|
||||||
member_count: Some(value.member_count),
|
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);
|
ret.insert(row.workspace_id, count);
|
||||||
}
|
}
|
||||||
for workspace_id in workspace_ids.iter() {
|
|
||||||
if !ret.contains_key(workspace_id) {
|
Ok(ret)
|
||||||
ret.insert(*workspace_id, 0);
|
}
|
||||||
}
|
|
||||||
|
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)
|
Ok(ret)
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,7 @@ impl Default for ViewLayout {
|
||||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||||
pub struct QueryWorkspaceParam {
|
pub struct QueryWorkspaceParam {
|
||||||
pub include_member_count: Option<bool>,
|
pub include_member_count: Option<bool>,
|
||||||
|
pub include_role: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||||
|
|
|
||||||
|
|
@ -338,10 +338,16 @@ async fn list_workspace_handler(
|
||||||
state: Data<AppState>,
|
state: Data<AppState>,
|
||||||
query: web::Query<QueryWorkspaceParam>,
|
query: web::Query<QueryWorkspaceParam>,
|
||||||
) -> Result<JsonAppResponse<Vec<AFWorkspace>>> {
|
) -> Result<JsonAppResponse<Vec<AFWorkspace>>> {
|
||||||
|
let QueryWorkspaceParam {
|
||||||
|
include_member_count,
|
||||||
|
include_role,
|
||||||
|
} = query.into_inner();
|
||||||
|
|
||||||
let workspaces = workspace::ops::get_all_user_workspaces(
|
let workspaces = workspace::ops::get_all_user_workspaces(
|
||||||
&state.pg_pool,
|
&state.pg_pool,
|
||||||
&uuid,
|
&uuid,
|
||||||
query.into_inner().include_member_count.unwrap_or(false),
|
include_member_count.unwrap_or(false),
|
||||||
|
include_role.unwrap_or(false),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(AppResponse::Ok().with_data(workspaces).into())
|
Ok(AppResponse::Ok().with_data(workspaces).into())
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,7 @@ pub async fn get_all_user_workspaces(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
user_uuid: &Uuid,
|
||||||
include_member_count: bool,
|
include_member_count: bool,
|
||||||
|
include_role: bool,
|
||||||
) -> Result<Vec<AFWorkspace>, AppResponseError> {
|
) -> Result<Vec<AFWorkspace>, AppResponseError> {
|
||||||
let workspaces = select_all_user_workspaces(pg_pool, user_uuid).await?;
|
let workspaces = select_all_user_workspaces(pg_pool, user_uuid).await?;
|
||||||
let mut workspaces = workspaces
|
let mut workspaces = workspaces
|
||||||
|
|
@ -273,10 +274,23 @@ pub async fn get_all_user_workspaces(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|row| row.workspace_id)
|
.map(|row| row.workspace_id)
|
||||||
.collect::<Vec<_>>();
|
.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() {
|
for workspace in workspaces.iter_mut() {
|
||||||
if let Some(member_count) = member_count_by_workspace_id.get(&workspace.workspace_id) {
|
if let Some(member_count) = member_count_by_workspace_id.remove(&workspace.workspace_id) {
|
||||||
workspace.member_count = Some(*member_count);
|
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;
|
.workspace_id;
|
||||||
|
|
||||||
let (bob_client, bob) = generate_unique_registered_user_client().await;
|
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
|
alice_client
|
||||||
.invite_workspace_members(
|
.invite_workspace_members(
|
||||||
alice_workspace_id.to_string().as_str(),
|
alice_workspace_id.to_string().as_str(),
|
||||||
|
|
@ -94,16 +103,49 @@ async fn invite_workspace_crud() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(accepted_invs.len(), 1);
|
assert_eq!(accepted_invs.len(), 1);
|
||||||
|
|
||||||
// workspace now have 2 members
|
{
|
||||||
let member_count = alice_client
|
// alice's view of the workspaces
|
||||||
.get_workspaces_opt(QueryWorkspaceParam {
|
let workspaces = alice_client
|
||||||
include_member_count: Some(true),
|
.get_workspaces_opt(QueryWorkspaceParam {
|
||||||
})
|
include_member_count: Some(true),
|
||||||
.await
|
include_role: Some(true),
|
||||||
.unwrap()
|
})
|
||||||
.first()
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
.member_count
|
|
||||||
.unwrap();
|
assert_eq!(workspaces.len(), 1);
|
||||||
assert_eq!(member_count, 2);
|
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…
Reference in New Issue