feat: improve email workspace invitations

This commit is contained in:
Zack Fu Zi Xiang 2024-04-30 11:07:29 +08:00
parent 721f0c759b
commit 9adf3f883c
No known key found for this signature in database
5 changed files with 78 additions and 17 deletions

View File

@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT invitee_email\n FROM public.af_workspace_invitation\n WHERE workspace_id = $1\n AND status = 0\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "invitee_email",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
false
]
},
"hash": "374c2d7b26f923328edd09b0d515d59426119615a8d5d8a46101f6ccec00d617"
}

View File

@ -30,7 +30,8 @@ RUN cargo build --profile=release --features "${FEATURES}" --bin appflowy_cloud
FROM debian:bookworm-slim AS runtime
WORKDIR /app
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends openssl \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& update-ca-certificates \
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \

View File

@ -4,7 +4,7 @@ use sqlx::{
types::{uuid, Uuid},
Executor, PgPool, Postgres, Transaction,
};
use std::ops::DerefMut;
use std::{collections::HashSet, ops::DerefMut};
use tracing::{event, instrument};
use crate::pg_row::AFWorkspaceMemberPermRow;
@ -705,3 +705,22 @@ pub async fn select_workspace_member_count_from_workspace_id(
.await?;
Ok(workspace_count)
}
#[inline]
pub async fn select_workspace_pending_invitations(
pool: &PgPool,
workspace_id: &Uuid,
) -> Result<HashSet<String>, AppError> {
let invitee_emails = sqlx::query_scalar!(
r#"
SELECT invitee_email
FROM public.af_workspace_invitation
WHERE workspace_id = $1
AND status = 0
"#,
workspace_id
)
.fetch_all(pool)
.await?;
Ok(invitee_emails.into_iter().collect())
}

View File

@ -297,11 +297,11 @@ async fn post_accept_workspace_invite_handler(
#[instrument(skip_all, err)]
async fn get_workspace_members_handler(
user_uuid: UserUuid,
_user_uuid: UserUuid,
state: Data<AppState>,
workspace_id: web::Path<Uuid>,
) -> Result<JsonAppResponse<Vec<AFWorkspaceMember>>> {
let members = workspace::ops::get_workspace_members(&state.pg_pool, &user_uuid, &workspace_id)
let members = workspace::ops::get_workspace_members(&state.pg_pool, &workspace_id)
.await?
.into_iter()
.map(|member| AFWorkspaceMember {

View File

@ -178,19 +178,39 @@ pub async fn invite_workspace_members(
.context("Begin transaction to invite workspace members")?;
let admin_token = gotrue_admin.token(gotrue_client).await?;
for invitation in invitations {
let inviter_name = database::user::select_name_from_uuid(pg_pool, inviter).await?;
let workspace_name =
database::workspace::select_workspace_name_from_workspace_id(pg_pool, workspace_id)
.await?
.unwrap_or_default();
let workspace_member_count =
database::workspace::select_workspace_member_count_from_workspace_id(pg_pool, workspace_id)
.await?
.unwrap_or_default()
.to_string();
let inviter_name = database::user::select_name_from_uuid(pg_pool, inviter).await?;
let workspace_name =
database::workspace::select_workspace_name_from_workspace_id(pg_pool, workspace_id)
.await?
.unwrap_or_default();
let workspace_member_count =
database::workspace::select_workspace_member_count_from_workspace_id(pg_pool, workspace_id)
.await?
.unwrap_or_default();
let workspace_members_by_email: HashMap<_, _> =
database::workspace::select_workspace_member_list(pg_pool, workspace_id)
.await?
.into_iter()
.map(|row| (row.email, row.role))
.collect();
let pending_invitations =
database::workspace::select_workspace_pending_invitations(pg_pool, workspace_id).await?;
// default icon until we have workspace icon
for invitation in invitations {
if workspace_members_by_email.contains_key(&invitation.email) {
tracing::warn!("User already in workspace: {}", invitation.email);
continue;
}
if pending_invitations.contains(&invitation.email) {
tracing::warn!("User already invited: {}", invitation.email);
continue;
}
let inviter_name = inviter_name.clone();
let workspace_name = workspace_name.clone();
let workspace_member_count = workspace_member_count.to_string();
// use default icon until we have workspace icon
let workspace_icon_url =
"https://miro.medium.com/v2/resize:fit:2400/1*mTPfm7CwU31-tLhtLNkyJw.png".to_string();
let user_icon_url =
@ -390,7 +410,6 @@ pub async fn remove_workspace_members(
pub async fn get_workspace_members(
pg_pool: &PgPool,
_user_uuid: &Uuid,
workspace_id: &Uuid,
) -> Result<Vec<AFWorkspaceMemberRow>, AppResponseError> {
Ok(select_workspace_member_list(pg_pool, workspace_id).await?)