chore: add specific error code for wrong invitee
This commit is contained in:
parent
78353f751f
commit
4b59574392
|
|
@ -142,6 +142,9 @@ pub enum AppError {
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
InvalidFolderView(String),
|
InvalidFolderView(String),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
NotInviteeOfWorkspaceInvitation(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppError {
|
impl AppError {
|
||||||
|
|
@ -208,6 +211,7 @@ impl AppError {
|
||||||
AppError::InvalidContentType(_) => ErrorCode::InvalidContentType,
|
AppError::InvalidContentType(_) => ErrorCode::InvalidContentType,
|
||||||
AppError::InvalidPublishedOutline(_) => ErrorCode::InvalidPublishedOutline,
|
AppError::InvalidPublishedOutline(_) => ErrorCode::InvalidPublishedOutline,
|
||||||
AppError::InvalidFolderView(_) => ErrorCode::InvalidFolderView,
|
AppError::InvalidFolderView(_) => ErrorCode::InvalidFolderView,
|
||||||
|
AppError::NotInviteeOfWorkspaceInvitation(_) => ErrorCode::NotInviteeOfWorkspaceInvitation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,6 +332,7 @@ pub enum ErrorCode {
|
||||||
AppleRevokeTokenError = 1038,
|
AppleRevokeTokenError = 1038,
|
||||||
InvalidPublishedOutline = 1039,
|
InvalidPublishedOutline = 1039,
|
||||||
InvalidFolderView = 1040,
|
InvalidFolderView = 1040,
|
||||||
|
NotInviteeOfWorkspaceInvitation = 1041,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorCode {
|
impl ErrorCode {
|
||||||
|
|
|
||||||
|
|
@ -1376,3 +1376,24 @@ pub async fn delete_reaction_from_comment<'a, E: Executor<'a, Database = Postgre
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn select_user_is_invitee_for_workspace_invitation(
|
||||||
|
pg_pool: &PgPool,
|
||||||
|
invitee_uuid: &Uuid,
|
||||||
|
invite_id: &Uuid,
|
||||||
|
) -> Result<bool, AppError> {
|
||||||
|
let res = sqlx::query_scalar!(
|
||||||
|
r#"
|
||||||
|
SELECT EXISTS(
|
||||||
|
SELECT 1
|
||||||
|
FROM af_workspace_invitation
|
||||||
|
WHERE id = $1 AND invitee_email = (SELECT email FROM af_user WHERE uuid = $2)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
invite_id,
|
||||||
|
invitee_uuid,
|
||||||
|
)
|
||||||
|
.fetch_one(pg_pool)
|
||||||
|
.await?;
|
||||||
|
res.map_or(Ok(false), Ok)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -340,12 +340,14 @@ async fn post_accept_workspace_invite_handler(
|
||||||
) -> Result<JsonAppResponse<()>> {
|
) -> Result<JsonAppResponse<()>> {
|
||||||
let _is_new = verify_token(&auth.token, state.as_ref()).await?;
|
let _is_new = verify_token(&auth.token, state.as_ref()).await?;
|
||||||
let user_uuid = auth.uuid()?;
|
let user_uuid = auth.uuid()?;
|
||||||
|
let user_uid = state.user_cache.get_user_uid(&user_uuid).await?;
|
||||||
let invite_id = invite_id.into_inner();
|
let invite_id = invite_id.into_inner();
|
||||||
// TODO(zack): insert a workspace member in the af_workspace_member by calling workspace::ops::add_workspace_members.
|
// TODO(zack): insert a workspace member in the af_workspace_member by calling workspace::ops::add_workspace_members.
|
||||||
// Currently, when the server get restarted, the policy in access control will be lost.
|
// Currently, when the server get restarted, the policy in access control will be lost.
|
||||||
workspace::ops::accept_workspace_invite(
|
workspace::ops::accept_workspace_invite(
|
||||||
&state.pg_pool,
|
&state.pg_pool,
|
||||||
&state.workspace_access_control,
|
&state.workspace_access_control,
|
||||||
|
user_uid,
|
||||||
&user_uuid,
|
&user_uuid,
|
||||||
&invite_id,
|
&invite_id,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -302,12 +302,21 @@ pub async fn open_workspace(
|
||||||
pub async fn accept_workspace_invite(
|
pub async fn accept_workspace_invite(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
workspace_access_control: &impl WorkspaceAccessControl,
|
workspace_access_control: &impl WorkspaceAccessControl,
|
||||||
|
user_uid: i64,
|
||||||
user_uuid: &Uuid,
|
user_uuid: &Uuid,
|
||||||
invite_id: &Uuid,
|
invite_id: &Uuid,
|
||||||
) -> Result<(), AppError> {
|
) -> Result<(), AppError> {
|
||||||
let mut txn = pg_pool.begin().await?;
|
let mut txn = pg_pool.begin().await?;
|
||||||
update_workspace_invitation_set_status_accepted(&mut txn, user_uuid, invite_id).await?;
|
|
||||||
let inv = get_invitation_by_id(&mut txn, invite_id).await?;
|
let inv = get_invitation_by_id(&mut txn, invite_id).await?;
|
||||||
|
if let Some(invitee_uid) = inv.invitee_uid {
|
||||||
|
if invitee_uid != user_uid {
|
||||||
|
return Err(AppError::NotInviteeOfWorkspaceInvitation(format!(
|
||||||
|
"User with uid {} is not the invitee for invite_id {}",
|
||||||
|
user_uid, invite_id
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_workspace_invitation_set_status_accepted(&mut txn, user_uuid, invite_id).await?;
|
||||||
let invited_uid = inv
|
let invited_uid = inv
|
||||||
.invitee_uid
|
.invitee_uid
|
||||||
.ok_or_else(|| AppError::Internal(anyhow::anyhow!("Invitee uid is missing for {:?}", inv)))?;
|
.ok_or_else(|| AppError::Internal(anyhow::anyhow!("Invitee uid is missing for {:?}", inv)))?;
|
||||||
|
|
@ -469,6 +478,14 @@ pub async fn get_workspace_invitations_for_user(
|
||||||
user_uuid: &Uuid,
|
user_uuid: &Uuid,
|
||||||
invite_id: &Uuid,
|
invite_id: &Uuid,
|
||||||
) -> Result<AFWorkspaceInvitation, AppError> {
|
) -> Result<AFWorkspaceInvitation, AppError> {
|
||||||
|
let user_is_invitee =
|
||||||
|
select_user_is_invitee_for_workspace_invitation(pg_pool, user_uuid, invite_id).await?;
|
||||||
|
if !user_is_invitee {
|
||||||
|
return Err(AppError::NotInviteeOfWorkspaceInvitation(format!(
|
||||||
|
"User with uuid {} is not the invitee for invite_id {}",
|
||||||
|
user_uuid, invite_id
|
||||||
|
)));
|
||||||
|
}
|
||||||
let invitation = select_workspace_invitation_for_user(pg_pool, user_uuid, invite_id).await?;
|
let invitation = select_workspace_invitation_for_user(pg_pool, user_uuid, invite_id).await?;
|
||||||
Ok(invitation)
|
Ok(invitation)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use app_error::ErrorCode;
|
||||||
use client_api_test::generate_unique_registered_user_client;
|
use client_api_test::generate_unique_registered_user_client;
|
||||||
use database_entity::dto::{AFRole, AFWorkspaceInvitationStatus};
|
use database_entity::dto::{AFRole, AFWorkspaceInvitationStatus};
|
||||||
use shared_entity::dto::workspace_dto::{QueryWorkspaceParam, WorkspaceMemberInvitation};
|
use shared_entity::dto::workspace_dto::{QueryWorkspaceParam, WorkspaceMemberInvitation};
|
||||||
|
|
@ -61,6 +62,18 @@ async fn invite_workspace_crud() {
|
||||||
assert_eq!(invitation.status, AFWorkspaceInvitationStatus::Pending);
|
assert_eq!(invitation.status, AFWorkspaceInvitationStatus::Pending);
|
||||||
assert_eq!(invitation.member_count.unwrap_or(0), 1);
|
assert_eq!(invitation.member_count.unwrap_or(0), 1);
|
||||||
|
|
||||||
|
let (charlie_client, _charlie) = generate_unique_registered_user_client().await;
|
||||||
|
let err = charlie_client
|
||||||
|
.get_workspace_invitation(&invite_id)
|
||||||
|
.await
|
||||||
|
.unwrap_err();
|
||||||
|
assert_eq!(err.code, ErrorCode::NotInviteeOfWorkspaceInvitation);
|
||||||
|
let err = charlie_client
|
||||||
|
.accept_workspace_invitation(&invite_id)
|
||||||
|
.await
|
||||||
|
.unwrap_err();
|
||||||
|
assert_eq!(err.code, ErrorCode::NotInviteeOfWorkspaceInvitation);
|
||||||
|
|
||||||
bob_client
|
bob_client
|
||||||
.accept_workspace_invitation(&invite_id)
|
.accept_workspace_invitation(&invite_id)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue