diff --git a/frontend/rust-lib/event-integration/src/event_builder.rs b/frontend/rust-lib/event-integration/src/event_builder.rs index fa20de726f..e25e6629bf 100644 --- a/frontend/rust-lib/event-integration/src/event_builder.rs +++ b/frontend/rust-lib/event-integration/src/event_builder.rs @@ -62,14 +62,12 @@ impl EventBuilder { let response = self.get_response(); match response.clone().parse::() { Ok(Ok(data)) => data, - Ok(Err(e)) => { - panic!( - "Parser {:?} failed: {:?}, response {:?}", - std::any::type_name::(), - e, - response - ) - }, + Ok(Err(e)) => panic!( + "Parser {:?} failed: {:?}, response {:?}", + std::any::type_name::(), + e, + response + ), Err(e) => panic!( "Dispatch {:?} failed: {:?}, response {:?}", std::any::type_name::(), diff --git a/frontend/rust-lib/event-integration/src/folder_event.rs b/frontend/rust-lib/event-integration/src/folder_event.rs index af426d1615..c388b78688 100644 --- a/frontend/rust-lib/event-integration/src/folder_event.rs +++ b/frontend/rust-lib/event-integration/src/folder_event.rs @@ -3,11 +3,13 @@ use flowy_folder::entities::*; use flowy_folder::event_map::FolderEvent; use flowy_folder::event_map::FolderEvent::*; use flowy_user::entities::{ - AddWorkspaceMemberPB, QueryWorkspacePB, RemoveWorkspaceMemberPB, RepeatedWorkspaceMemberPB, + AcceptWorkspaceInvitationPB, AddWorkspaceMemberPB, QueryWorkspacePB, RemoveWorkspaceMemberPB, + RepeatedWorkspaceInvitationPB, RepeatedWorkspaceMemberPB, WorkspaceMemberInvitationPB, WorkspaceMemberPB, }; use flowy_user::errors::FlowyError; use flowy_user::event_map::UserEvent; +use flowy_user_pub::entities::WorkspaceRole; use crate::event_builder::EventBuilder; use crate::EventIntegrationTest; @@ -24,6 +26,41 @@ impl EventIntegrationTest { .await; } + pub async fn invite_workspace_member( + &self, + workspace_id: &str, + email: &str, + role: WorkspaceRole, + ) { + EventBuilder::new(self.clone()) + .event(UserEvent::InviteWorkspaceMember) + .payload(WorkspaceMemberInvitationPB { + workspace_id: workspace_id.to_string(), + invitee_email: email.to_string(), + role: role.into(), + }) + .async_send() + .await; + } + + pub async fn list_workspace_invitations(&self) -> RepeatedWorkspaceInvitationPB { + EventBuilder::new(self.clone()) + .event(UserEvent::ListWorkspaceInvitations) + .async_send() + .await + .parse() + } + + pub async fn accept_workspace_invitation(&self, invitation_id: &str) { + EventBuilder::new(self.clone()) + .event(UserEvent::AcceptWorkspaceInvitation) + .payload(AcceptWorkspaceInvitationPB { + invite_id: invitation_id.to_string(), + }) + .async_send() + .await; + } + pub async fn delete_workspace_member(&self, workspace_id: &str, email: &str) { EventBuilder::new(self.clone()) .event(UserEvent::RemoveWorkspaceMember) diff --git a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/member_test.rs b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/member_test.rs index fff097275a..95eebc17eb 100644 --- a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/member_test.rs +++ b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/member_test.rs @@ -1,5 +1,36 @@ use event_integration::user_event::user_localhost_af_cloud; use event_integration::EventIntegrationTest; +use flowy_user_pub::entities::WorkspaceRole; + +use crate::user::af_cloud_test::workspace_test::get_synced_workspaces; + +#[tokio::test] +async fn af_cloud_invite_workspace_member() { + user_localhost_af_cloud().await; + let test_1 = EventIntegrationTest::new().await; + let user_1 = test_1.af_cloud_sign_up().await; + + let test_2 = EventIntegrationTest::new().await; + let user_2 = test_2.af_cloud_sign_up().await; + + test_1 + .invite_workspace_member(&user_1.workspace_id, &user_2.email, WorkspaceRole::Member) + .await; + + let invitations = test_2.list_workspace_invitations().await; + let target_invi = invitations + .items + .into_iter() + .find(|i| i.inviter_name == user_1.name && i.workspace_id == user_1.workspace_id) + .unwrap(); + + test_2 + .accept_workspace_invitation(&target_invi.invite_id) + .await; + + let workspaces = get_synced_workspaces(&test_2, user_2.id).await; + assert_eq!(workspaces.len(), 2); +} #[tokio::test] async fn af_cloud_add_workspace_member_test() { diff --git a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/workspace_test.rs b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/workspace_test.rs index 176a39aa9a..12dbbd1c1c 100644 --- a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/workspace_test.rs +++ b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/workspace_test.rs @@ -99,7 +99,10 @@ async fn af_cloud_open_workspace_test() { assert_eq!(views[2].name, "my second document".to_string()); } -async fn get_synced_workspaces(test: &EventIntegrationTest, user_id: i64) -> Vec { +pub async fn get_synced_workspaces( + test: &EventIntegrationTest, + user_id: i64, +) -> Vec { let _workspaces = test.get_all_workspaces().await.items; let sub_id = user_id.to_string(); let rx = test diff --git a/frontend/rust-lib/flowy-database2/src/services/calculations/service.rs b/frontend/rust-lib/flowy-database2/src/services/calculations/service.rs index dda8a68f3e..4a5a454360 100644 --- a/frontend/rust-lib/flowy-database2/src/services/calculations/service.rs +++ b/frontend/rust-lib/flowy-database2/src/services/calculations/service.rs @@ -69,7 +69,7 @@ impl CalculationsService { } } - fn median(array: &Vec) -> f64 { + fn median(array: &[f64]) -> f64 { if (array.len() % 2) == 0 { let left = array.len() / 2 - 1; let right = array.len() / 2; diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs index 586081b033..65a6df5310 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs @@ -17,8 +17,8 @@ use parking_lot::RwLock; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_user_pub::cloud::{UserCloudService, UserCollabParams, UserUpdate, UserUpdateReceiver}; use flowy_user_pub::entities::{ - AFCloudOAuthParams, AuthResponse, Role, UpdateUserProfileParams, UserCredentials, UserProfile, - UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember, + AFCloudOAuthParams, AuthResponse, UpdateUserProfileParams, UserCredentials, UserProfile, + UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember, WorkspaceRole, }; use lib_infra::box_any::BoxAny; use lib_infra::future::FutureResult; @@ -206,7 +206,7 @@ where &self, invitee_email: String, workspace_id: String, - role: Role, + role: WorkspaceRole, ) -> FutureResult<(), Error> { let try_get_client = self.server.try_get_client(); FutureResult::new(async move { @@ -269,7 +269,7 @@ where &self, user_email: String, workspace_id: String, - role: Role, + role: WorkspaceRole, ) -> FutureResult<(), Error> { let try_get_client = self.server.try_get_client(); FutureResult::new(async move { diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs index c24ddbb51e..e0fe27ef84 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs @@ -3,9 +3,8 @@ use client_api::entity::auth_dto::{UpdateUserParams, UserMetaData}; use client_api::entity::{AFRole, AFUserProfile, AFWorkspaceInvitationStatus, AFWorkspaceMember}; use flowy_user_pub::entities::{ - Authenticator, Role, UpdateUserProfileParams, UserProfile, WorkspaceInvitationStatus, - WorkspaceMember, USER_METADATA_ICON_URL, USER_METADATA_OPEN_AI_KEY, - USER_METADATA_STABILITY_AI_KEY, + Authenticator, UpdateUserProfileParams, UserProfile, WorkspaceInvitationStatus, WorkspaceMember, + WorkspaceRole, 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; @@ -68,19 +67,19 @@ pub fn user_profile_from_af_profile( }) } -pub fn to_af_role(role: Role) -> AFRole { +pub fn to_af_role(role: WorkspaceRole) -> AFRole { match role { - Role::Owner => AFRole::Owner, - Role::Member => AFRole::Member, - Role::Guest => AFRole::Guest, + WorkspaceRole::Owner => AFRole::Owner, + WorkspaceRole::Member => AFRole::Member, + WorkspaceRole::Guest => AFRole::Guest, } } -pub fn from_af_role(role: AFRole) -> Role { +pub fn from_af_role(role: AFRole) -> WorkspaceRole { match role { - AFRole::Owner => Role::Owner, - AFRole::Member => Role::Member, - AFRole::Guest => Role::Guest, + AFRole::Owner => WorkspaceRole::Owner, + AFRole::Member => WorkspaceRole::Member, + AFRole::Guest => WorkspaceRole::Guest, } } diff --git a/frontend/rust-lib/flowy-user-pub/src/cloud.rs b/frontend/rust-lib/flowy-user-pub/src/cloud.rs index e12d26a3ba..695d90d499 100644 --- a/frontend/rust-lib/flowy-user-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-user-pub/src/cloud.rs @@ -15,8 +15,9 @@ use tokio_stream::wrappers::WatchStream; use uuid::Uuid; use crate::entities::{ - AuthResponse, Authenticator, Role, UpdateUserProfileParams, UserCredentials, UserProfile, + AuthResponse, Authenticator, UpdateUserProfileParams, UserCredentials, UserProfile, UserTokenState, UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember, + WorkspaceRole, }; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -195,7 +196,7 @@ pub trait UserCloudService: Send + Sync + 'static { &self, invitee_email: String, workspace_id: String, - role: Role, + role: WorkspaceRole, ) -> FutureResult<(), Error> { FutureResult::new(async { Ok(()) }) } @@ -223,7 +224,7 @@ pub trait UserCloudService: Send + Sync + 'static { &self, user_email: String, workspace_id: String, - role: Role, + role: WorkspaceRole, ) -> FutureResult<(), Error> { FutureResult::new(async { Ok(()) }) } diff --git a/frontend/rust-lib/flowy-user-pub/src/entities.rs b/frontend/rust-lib/flowy-user-pub/src/entities.rs index f9b6f8a790..45fa0a7919 100644 --- a/frontend/rust-lib/flowy-user-pub/src/entities.rs +++ b/frontend/rust-lib/flowy-user-pub/src/entities.rs @@ -381,7 +381,7 @@ pub enum UserTokenState { } #[derive(Clone, Debug)] -pub enum Role { +pub enum WorkspaceRole { Owner, Member, Guest, @@ -389,7 +389,7 @@ pub enum Role { pub struct WorkspaceMember { pub email: String, - pub role: Role, + pub role: WorkspaceRole, pub name: String, } diff --git a/frontend/rust-lib/flowy-user/src/entities/workspace.rs b/frontend/rust-lib/flowy-user/src/entities/workspace.rs index 38cd56db79..3028fb0324 100644 --- a/frontend/rust-lib/flowy-user/src/entities/workspace.rs +++ b/frontend/rust-lib/flowy-user/src/entities/workspace.rs @@ -1,7 +1,7 @@ use validator::Validate; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_user_pub::entities::{Role, WorkspaceInvitation, WorkspaceMember}; +use flowy_user_pub::entities::{WorkspaceInvitation, WorkspaceMember, WorkspaceRole}; use lib_infra::validator_fn::required_not_empty_str; #[derive(ProtoBuf, Default, Clone)] @@ -13,7 +13,7 @@ pub struct WorkspaceMemberPB { pub name: String, #[pb(index = 3)] - pub role: AFRolePB, + pub role: WorkspaceRolePB, } impl From for WorkspaceMemberPB { @@ -43,16 +43,16 @@ pub struct WorkspaceMemberInvitationPB { pub invitee_email: String, #[pb(index = 3)] - pub role: AFRolePB, + pub role: WorkspaceRolePB, } -#[derive(ProtoBuf, Default, Clone)] +#[derive(Debug, ProtoBuf, Default, Clone)] pub struct RepeatedWorkspaceInvitationPB { #[pb(index = 1)] pub items: Vec, } -#[derive(ProtoBuf, Default, Clone)] +#[derive(Debug, ProtoBuf, Default, Clone)] pub struct WorkspaceInvitationPB { #[pb(index = 1)] pub invite_id: String, @@ -131,33 +131,33 @@ pub struct UpdateWorkspaceMemberPB { pub email: String, #[pb(index = 3)] - pub role: AFRolePB, + pub role: WorkspaceRolePB, } #[derive(ProtoBuf_Enum, Clone, Default)] -pub enum AFRolePB { +pub enum WorkspaceRolePB { Owner = 0, Member = 1, #[default] Guest = 2, } -impl From for Role { - fn from(value: AFRolePB) -> Self { +impl From for WorkspaceRole { + fn from(value: WorkspaceRolePB) -> Self { match value { - AFRolePB::Owner => Role::Owner, - AFRolePB::Member => Role::Member, - AFRolePB::Guest => Role::Guest, + WorkspaceRolePB::Owner => WorkspaceRole::Owner, + WorkspaceRolePB::Member => WorkspaceRole::Member, + WorkspaceRolePB::Guest => WorkspaceRole::Guest, } } } -impl From for AFRolePB { - fn from(value: Role) -> Self { +impl From for WorkspaceRolePB { + fn from(value: WorkspaceRole) -> Self { match value { - Role::Owner => AFRolePB::Owner, - Role::Member => AFRolePB::Member, - Role::Guest => AFRolePB::Guest, + WorkspaceRole::Owner => WorkspaceRolePB::Owner, + WorkspaceRole::Member => WorkspaceRolePB::Member, + WorkspaceRole::Guest => WorkspaceRolePB::Guest, } } } diff --git a/frontend/rust-lib/flowy-user/src/event_handler.rs b/frontend/rust-lib/flowy-user/src/event_handler.rs index 778c3ec09a..19a4dadafd 100644 --- a/frontend/rust-lib/flowy-user/src/event_handler.rs +++ b/frontend/rust-lib/flowy-user/src/event_handler.rs @@ -711,7 +711,7 @@ pub async fn change_workspace_icon_handler( } #[tracing::instrument(level = "debug", skip_all, err)] -pub async fn invite_members_to_workspace_handler( +pub async fn invite_workspace_member_handler( param: AFPluginData, manager: AFPluginState>, ) -> Result<(), FlowyError> { @@ -720,8 +720,7 @@ pub async fn invite_members_to_workspace_handler( manager .invite_member_to_workspace(param.workspace_id, param.invitee_email, param.role.into()) .await?; - - todo!() + Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] diff --git a/frontend/rust-lib/flowy-user/src/event_map.rs b/frontend/rust-lib/flowy-user/src/event_map.rs index 2eaa36623d..9cc2c01762 100644 --- a/frontend/rust-lib/flowy-user/src/event_map.rs +++ b/frontend/rust-lib/flowy-user/src/event_map.rs @@ -67,7 +67,7 @@ pub fn init(user_manager: Weak) -> AFPlugin { .event(UserEvent::RenameWorkspace, rename_workspace_handler) .event(UserEvent::ChangeWorkspaceIcon, change_workspace_icon_handler) - .event(UserEvent::InviteMembersToWorkspace, invite_members_to_workspace_handler) + .event(UserEvent::InviteWorkspaceMember, invite_workspace_member_handler) .event(UserEvent::ListWorkspaceInvitations, list_workspace_invitations_handler) .event(UserEvent::AcceptWorkspaceInvitation, accept_workspace_invitations_handler) } @@ -216,7 +216,7 @@ pub enum UserEvent { ChangeWorkspaceIcon = 45, #[event(input = "WorkspaceMemberInvitationPB")] - InviteMembersToWorkspace = 46, + InviteWorkspaceMember = 46, #[event(output = "RepeatedWorkspaceInvitationPB")] ListWorkspaceInvitations = 47, diff --git a/frontend/rust-lib/flowy-user/src/user_manager/manager_user_workspace.rs b/frontend/rust-lib/flowy-user/src/user_manager/manager_user_workspace.rs index 138962a87b..927ea7dcc9 100644 --- a/frontend/rust-lib/flowy-user/src/user_manager/manager_user_workspace.rs +++ b/frontend/rust-lib/flowy-user/src/user_manager/manager_user_workspace.rs @@ -10,7 +10,7 @@ use flowy_folder_pub::entities::{AppFlowyData, ImportData}; use flowy_sqlite::schema::user_workspace_table; use flowy_sqlite::{query_dsl::*, DBConnection, ExpressionMethods}; use flowy_user_pub::entities::{ - Role, UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember, + UserWorkspace, WorkspaceInvitation, WorkspaceInvitationStatus, WorkspaceMember, WorkspaceRole, }; use lib_dispatch::prelude::af_spawn; @@ -200,7 +200,7 @@ impl UserManager { &self, workspace_id: String, invitee_email: String, - role: Role, + role: WorkspaceRole, ) -> FlowyResult<()> { self .cloud_services @@ -272,7 +272,7 @@ impl UserManager { &self, user_email: String, workspace_id: String, - role: Role, + role: WorkspaceRole, ) -> FlowyResult<()> { self .cloud_services