mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: leave workspace api (#4942)
* feat: leave workpspace event * feat: add leave workspace event --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
@ -313,6 +313,17 @@ impl EventIntegrationTest {
|
|||||||
.async_send()
|
.async_send()
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn leave_workspace(&self, workspace_id: &str) {
|
||||||
|
let payload = UserWorkspaceIdPB {
|
||||||
|
workspace_id: workspace_id.to_string(),
|
||||||
|
};
|
||||||
|
EventBuilder::new(self.clone())
|
||||||
|
.event(UserEvent::LeaveWorkspace)
|
||||||
|
.payload(payload)
|
||||||
|
.async_send()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::user::af_cloud_test::util::get_synced_workspaces;
|
||||||
use event_integration::user_event::user_localhost_af_cloud;
|
use event_integration::user_event::user_localhost_af_cloud;
|
||||||
use event_integration::EventIntegrationTest;
|
use event_integration::EventIntegrationTest;
|
||||||
|
|
||||||
@ -45,3 +46,28 @@ async fn af_cloud_delete_workspace_member_test() {
|
|||||||
assert_eq!(members.len(), 1);
|
assert_eq!(members.len(), 1);
|
||||||
assert_eq!(members[0].email, user_1.email);
|
assert_eq!(members[0].email, user_1.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn af_cloud_leave_workspace_test() {
|
||||||
|
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
|
||||||
|
.add_workspace_member(&user_1.workspace_id, &user_2.email)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// test_2 should have 2 workspace
|
||||||
|
let workspaces = get_synced_workspaces(&test_2, user_2.id).await;
|
||||||
|
assert_eq!(workspaces.len(), 2);
|
||||||
|
|
||||||
|
// user_2 leaves the workspace
|
||||||
|
test_2.leave_workspace(&user_1.workspace_id).await;
|
||||||
|
|
||||||
|
// user_2 should have 1 workspace
|
||||||
|
let workspaces = get_synced_workspaces(&test_2, user_2.id).await;
|
||||||
|
assert_eq!(workspaces.len(), 1);
|
||||||
|
}
|
||||||
|
@ -2,4 +2,5 @@ mod anon_user_test;
|
|||||||
mod auth_test;
|
mod auth_test;
|
||||||
mod import_af_data_folder_test;
|
mod import_af_data_folder_test;
|
||||||
mod member_test;
|
mod member_test;
|
||||||
|
mod util;
|
||||||
mod workspace_test;
|
mod workspace_test;
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use event_integration::EventIntegrationTest;
|
||||||
|
use flowy_user::{
|
||||||
|
entities::{RepeatedUserWorkspacePB, UserWorkspacePB},
|
||||||
|
protobuf::UserNotification,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::util::receive_with_timeout;
|
||||||
|
|
||||||
|
pub async fn get_synced_workspaces(
|
||||||
|
test: &EventIntegrationTest,
|
||||||
|
user_id: i64,
|
||||||
|
) -> Vec<UserWorkspacePB> {
|
||||||
|
let _workspaces = test.get_all_workspaces().await.items;
|
||||||
|
let sub_id = user_id.to_string();
|
||||||
|
let rx = test
|
||||||
|
.notification_sender
|
||||||
|
.subscribe::<RepeatedUserWorkspacePB>(
|
||||||
|
&sub_id,
|
||||||
|
UserNotification::DidUpdateUserWorkspaces as i32,
|
||||||
|
);
|
||||||
|
receive_with_timeout(rx, Duration::from_secs(30))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.items
|
||||||
|
}
|
@ -1,11 +1,7 @@
|
|||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use event_integration::user_event::user_localhost_af_cloud;
|
use event_integration::user_event::user_localhost_af_cloud;
|
||||||
use event_integration::EventIntegrationTest;
|
use event_integration::EventIntegrationTest;
|
||||||
use flowy_user::entities::{RepeatedUserWorkspacePB, UserWorkspacePB};
|
|
||||||
use flowy_user::protobuf::UserNotification;
|
|
||||||
|
|
||||||
use crate::util::receive_with_timeout;
|
use crate::user::af_cloud_test::util::get_synced_workspaces;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn af_cloud_workspace_delete() {
|
async fn af_cloud_workspace_delete() {
|
||||||
@ -111,18 +107,3 @@ async fn af_cloud_open_workspace_test() {
|
|||||||
assert_eq!(views[1].name, "my first document".to_string());
|
assert_eq!(views[1].name, "my first document".to_string());
|
||||||
assert_eq!(views[2].name, "my second document".to_string());
|
assert_eq!(views[2].name, "my second document".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_synced_workspaces(test: &EventIntegrationTest, user_id: i64) -> Vec<UserWorkspacePB> {
|
|
||||||
let _workspaces = test.get_all_workspaces().await.items;
|
|
||||||
let sub_id = user_id.to_string();
|
|
||||||
let rx = test
|
|
||||||
.notification_sender
|
|
||||||
.subscribe::<RepeatedUserWorkspacePB>(
|
|
||||||
&sub_id,
|
|
||||||
UserNotification::DidUpdateUserWorkspaces as i32,
|
|
||||||
);
|
|
||||||
receive_with_timeout(rx, Duration::from_secs(30))
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.items
|
|
||||||
}
|
|
||||||
|
@ -346,6 +346,16 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn leave_workspace(&self, workspace_id: &str) -> FutureResult<(), FlowyError> {
|
||||||
|
let try_get_client = self.server.try_get_client();
|
||||||
|
let workspace_id = workspace_id.to_string();
|
||||||
|
FutureResult::new(async move {
|
||||||
|
let client = try_get_client?;
|
||||||
|
client.leave_workspace(&workspace_id).await?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_admin_client(client: &Arc<AFCloudClient>) -> FlowyResult<Client> {
|
async fn get_admin_client(client: &Arc<AFCloudClient>) -> FlowyResult<Client> {
|
||||||
|
@ -234,6 +234,10 @@ pub trait UserCloudService: Send + Sync + 'static {
|
|||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
objects: Vec<UserCollabParams>,
|
objects: Vec<UserCollabParams>,
|
||||||
) -> FutureResult<(), FlowyError>;
|
) -> FutureResult<(), FlowyError>;
|
||||||
|
|
||||||
|
fn leave_workspace(&self, workspace_id: &str) -> FutureResult<(), FlowyError> {
|
||||||
|
FutureResult::new(async { Ok(()) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UserUpdateReceiver = tokio::sync::mpsc::Receiver<UserUpdate>;
|
pub type UserUpdateReceiver = tokio::sync::mpsc::Receiver<UserUpdate>;
|
||||||
|
@ -709,3 +709,14 @@ pub async fn change_workspace_icon_handler(
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||||
|
pub async fn leave_workspace_handler(
|
||||||
|
param: AFPluginData<UserWorkspaceIdPB>,
|
||||||
|
manager: AFPluginState<Weak<UserManager>>,
|
||||||
|
) -> Result<(), FlowyError> {
|
||||||
|
let workspace_id = param.into_inner().workspace_id;
|
||||||
|
let manager = upgrade_manager(manager)?;
|
||||||
|
manager.leave_workspace(&workspace_id).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -64,6 +64,7 @@ pub fn init(user_manager: Weak<UserManager>) -> AFPlugin {
|
|||||||
.event(UserEvent::DeleteWorkspace, delete_workspace_handler)
|
.event(UserEvent::DeleteWorkspace, delete_workspace_handler)
|
||||||
.event(UserEvent::RenameWorkspace, rename_workspace_handler)
|
.event(UserEvent::RenameWorkspace, rename_workspace_handler)
|
||||||
.event(UserEvent::ChangeWorkspaceIcon, change_workspace_icon_handler)
|
.event(UserEvent::ChangeWorkspaceIcon, change_workspace_icon_handler)
|
||||||
|
.event(UserEvent::LeaveWorkspace, leave_workspace_handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||||
@ -208,6 +209,9 @@ pub enum UserEvent {
|
|||||||
|
|
||||||
#[event(input = "ChangeWorkspaceIconPB")]
|
#[event(input = "ChangeWorkspaceIconPB")]
|
||||||
ChangeWorkspaceIcon = 45,
|
ChangeWorkspaceIcon = 45,
|
||||||
|
|
||||||
|
#[event(input = "UserWorkspaceIdPB")]
|
||||||
|
LeaveWorkspace = 46,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UserStatusCallback: Send + Sync + 'static {
|
pub trait UserStatusCallback: Send + Sync + 'static {
|
||||||
|
@ -202,6 +202,19 @@ impl UserManager {
|
|||||||
save_user_workspaces(uid, conn, &[user_workspace])
|
save_user_workspaces(uid, conn, &[user_workspace])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn leave_workspace(&self, workspace_id: &str) -> FlowyResult<()> {
|
||||||
|
self
|
||||||
|
.cloud_services
|
||||||
|
.get_user_service()?
|
||||||
|
.leave_workspace(workspace_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// delete workspace from local sqlite db
|
||||||
|
let uid = self.user_id()?;
|
||||||
|
let conn = self.db_connection(uid)?;
|
||||||
|
delete_user_workspaces(conn, workspace_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_workspace(&self, workspace_id: &str) -> FlowyResult<()> {
|
pub async fn delete_workspace(&self, workspace_id: &str) -> FlowyResult<()> {
|
||||||
self
|
self
|
||||||
.cloud_services
|
.cloud_services
|
||||||
|
Reference in New Issue
Block a user