feat: workspace invite (#4827)

* feat: add rename and change icon for workspace cloud api

* feat: added created at field for UserWorkspacePB

* test: added view check after creating workspace

* fix: allow new_icon to be empty string

* feat: add invitation api cloud services

* chore: cargo clippy

* chore: merge conflict

* feat: add workspace invitation test

* fix: use back old role and af role

* chore: use 1.75 channel rust toolchain

* chore: added error for test case

* chore: added ci var

* chore: cargo clippy
This commit is contained in:
Zack
2024-04-11 14:47:34 +08:00
committed by GitHub
parent b51ff318a1
commit 828f312294
13 changed files with 379 additions and 34 deletions

View File

@ -4,18 +4,22 @@ use std::sync::Arc;
use anyhow::anyhow;
use client_api::entity::workspace_dto::{
CreateWorkspaceMember, CreateWorkspaceParam, PatchWorkspaceParam, WorkspaceMemberChangeset,
WorkspaceMemberInvitation,
};
use client_api::entity::{
AFRole, AFWorkspace, AuthProvider, CollabParams, CreateCollabParams, QueryCollab,
QueryCollabParams,
AFRole, AFWorkspace, AFWorkspaceInvitation, AuthProvider, CollabParams, CreateCollabParams,
};
use client_api::entity::{QueryCollab, QueryCollabParams};
use client_api::{Client, ClientConfiguration};
use collab_entity::{CollabObject, CollabType};
use parking_lot::RwLock;
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_user_pub::cloud::{UserCloudService, UserCollabParams, UserUpdate, UserUpdateReceiver};
use flowy_user_pub::entities::*;
use flowy_user_pub::entities::{
AFCloudOAuthParams, AuthResponse, Role, UpdateUserProfileParams, UserCredentials, UserProfile,
UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember,
};
use lib_infra::box_any::BoxAny;
use lib_infra::future::FutureResult;
use uuid::Uuid;
@ -27,6 +31,8 @@ use crate::af_cloud::impls::user::dto::{
use crate::af_cloud::impls::user::util::encryption_type_from_profile;
use crate::af_cloud::{AFCloudClient, AFServer};
use super::dto::{from_af_workspace_invitation_status, to_workspace_invitation_status};
pub(crate) struct AFCloudUserAuthServiceImpl<T> {
server: T,
user_change_recv: RwLock<Option<tokio::sync::mpsc::Receiver<UserUpdate>>>,
@ -197,6 +203,55 @@ where
})
}
fn invite_workspace_member(
&self,
invitee_email: String,
workspace_id: String,
role: Role,
) -> FutureResult<(), FlowyError> {
let try_get_client = self.server.try_get_client();
FutureResult::new(async move {
try_get_client?
.invite_workspace_members(
&workspace_id,
vec![WorkspaceMemberInvitation {
email: invitee_email,
role: to_af_role(role),
}],
)
.await?;
Ok(())
})
}
fn list_workspace_invitations(
&self,
filter: Option<WorkspaceInvitationStatus>,
) -> FutureResult<Vec<WorkspaceInvitation>, FlowyError> {
let try_get_client = self.server.try_get_client();
let filter = filter.map(to_workspace_invitation_status);
FutureResult::new(async move {
let r = try_get_client?
.list_workspace_invitations(filter)
.await?
.into_iter()
.map(to_workspace_invitation)
.collect();
Ok(r)
})
}
fn accept_workspace_invitations(&self, invite_id: String) -> FutureResult<(), FlowyError> {
let try_get_client = self.server.try_get_client();
FutureResult::new(async move {
try_get_client?
.accept_workspace_invitation(&invite_id)
.await?;
Ok(())
})
}
fn remove_workspace_member(
&self,
user_email: String,
@ -451,6 +506,18 @@ fn to_user_workspaces(workspaces: Vec<AFWorkspace>) -> Result<Vec<UserWorkspace>
Ok(result)
}
fn to_workspace_invitation(invi: AFWorkspaceInvitation) -> WorkspaceInvitation {
WorkspaceInvitation {
invite_id: invi.invite_id,
workspace_id: invi.workspace_id,
workspace_name: invi.workspace_name,
inviter_email: invi.inviter_email,
inviter_name: invi.inviter_name,
status: from_af_workspace_invitation_status(invi.status),
updated_at: invi.updated_at,
}
}
fn oauth_params_from_box_any(any: BoxAny) -> Result<AFCloudOAuthParams, FlowyError> {
let map: HashMap<String, String> = any.unbox_or_error()?;
let sign_in_url = map

View File

@ -1,10 +1,11 @@
use anyhow::Error;
use client_api::entity::auth_dto::{UpdateUserParams, UserMetaData};
use client_api::entity::{AFRole, AFUserProfile, AFWorkspaceMember};
use client_api::entity::{AFRole, AFUserProfile, AFWorkspaceInvitationStatus, AFWorkspaceMember};
use flowy_user_pub::entities::{
Authenticator, Role, UpdateUserProfileParams, UserProfile, WorkspaceMember,
USER_METADATA_ICON_URL, USER_METADATA_OPEN_AI_KEY, USER_METADATA_STABILITY_AI_KEY,
Authenticator, Role, UpdateUserProfileParams, UserProfile, WorkspaceInvitationStatus,
WorkspaceMember, USER_METADATA_ICON_URL, USER_METADATA_OPEN_AI_KEY,
USER_METADATA_STABILITY_AI_KEY,
};
use crate::af_cloud::impls::user::util::encryption_type_from_profile;
@ -90,3 +91,23 @@ pub fn from_af_workspace_member(member: AFWorkspaceMember) -> WorkspaceMember {
name: member.name,
}
}
pub fn to_workspace_invitation_status(
status: WorkspaceInvitationStatus,
) -> AFWorkspaceInvitationStatus {
match status {
WorkspaceInvitationStatus::Pending => AFWorkspaceInvitationStatus::Pending,
WorkspaceInvitationStatus::Accepted => AFWorkspaceInvitationStatus::Accepted,
WorkspaceInvitationStatus::Rejected => AFWorkspaceInvitationStatus::Rejected,
}
}
pub fn from_af_workspace_invitation_status(
status: AFWorkspaceInvitationStatus,
) -> WorkspaceInvitationStatus {
match status {
AFWorkspaceInvitationStatus::Pending => WorkspaceInvitationStatus::Pending,
AFWorkspaceInvitationStatus::Accepted => WorkspaceInvitationStatus::Accepted,
AFWorkspaceInvitationStatus::Rejected => WorkspaceInvitationStatus::Rejected,
}
}