mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: workspace service in user crate (#4373)
* refactor: user manager * feat: implement workspace service * refactor: migrate user data when sign up * chore: fmt * chore: enable beta cloud * chore: update ci * chore: trim slash
This commit is contained in:
@ -7,12 +7,13 @@ use flowy_sqlite::{
|
||||
prelude::*,
|
||||
schema::{collab_snapshot, collab_snapshot::dsl},
|
||||
};
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
|
||||
use lib_infra::util::timestamp;
|
||||
use std::sync::Weak;
|
||||
use tracing::debug;
|
||||
|
||||
pub struct SnapshotDBImpl(pub Weak<UserManager>);
|
||||
pub struct SnapshotDBImpl(pub Weak<AuthenticateUser>);
|
||||
|
||||
impl SnapshotPersistence for SnapshotDBImpl {
|
||||
fn create_snapshot(
|
||||
@ -24,16 +25,12 @@ impl SnapshotPersistence for SnapshotDBImpl {
|
||||
) -> Result<(), PersistenceError> {
|
||||
let collab_type = collab_type.clone();
|
||||
let object_id = object_id.to_string();
|
||||
let weak_user_session = self.0.clone();
|
||||
let weak_user = self.0.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
if let Some(pool) = weak_user_session
|
||||
if let Some(mut conn) = weak_user
|
||||
.upgrade()
|
||||
.and_then(|user_session| user_session.db_pool(uid).ok())
|
||||
.and_then(|authenticate_user| authenticate_user.get_sqlite_connection(uid).ok())
|
||||
{
|
||||
let mut conn = pool
|
||||
.get()
|
||||
.map_err(|e| PersistenceError::Internal(e.into()))?;
|
||||
|
||||
// Save the snapshot data to disk
|
||||
let result = CollabSnapshotSql::create(
|
||||
CollabSnapshotRow::new(object_id.clone(), collab_type.to_string(), encoded_v1),
|
||||
|
@ -1,25 +1,22 @@
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use collab_integrate::collab_builder::AppFlowyCollabBuilder;
|
||||
use collab_integrate::CollabKVDB;
|
||||
use flowy_database2::{DatabaseManager, DatabaseUser};
|
||||
use flowy_database_pub::cloud::DatabaseCloudService;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
use lib_infra::priority_task::TaskDispatcher;
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::sync::RwLock;
|
||||
pub struct DatabaseDepsResolver();
|
||||
|
||||
impl DatabaseDepsResolver {
|
||||
pub async fn resolve(
|
||||
user_manager: Weak<UserManager>,
|
||||
authenticate_user: Weak<AuthenticateUser>,
|
||||
task_scheduler: Arc<RwLock<TaskDispatcher>>,
|
||||
collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
cloud_service: Arc<dyn DatabaseCloudService>,
|
||||
) -> Arc<DatabaseManager> {
|
||||
let user = Arc::new(DatabaseUserImpl(user_manager));
|
||||
let user = Arc::new(DatabaseUserImpl(authenticate_user));
|
||||
Arc::new(DatabaseManager::new(
|
||||
user,
|
||||
task_scheduler,
|
||||
@ -29,7 +26,7 @@ impl DatabaseDepsResolver {
|
||||
}
|
||||
}
|
||||
|
||||
struct DatabaseUserImpl(Weak<UserManager>);
|
||||
struct DatabaseUserImpl(Weak<AuthenticateUser>);
|
||||
impl DatabaseUser for DatabaseUserImpl {
|
||||
fn user_id(&self) -> Result<i64, FlowyError> {
|
||||
self
|
||||
@ -39,14 +36,6 @@ impl DatabaseUser for DatabaseUserImpl {
|
||||
.user_id()
|
||||
}
|
||||
|
||||
fn token(&self) -> Result<Option<String>, FlowyError> {
|
||||
self
|
||||
.0
|
||||
.upgrade()
|
||||
.ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?
|
||||
.token()
|
||||
}
|
||||
|
||||
fn collab_db(&self, uid: i64) -> Result<Weak<CollabKVDB>, FlowyError> {
|
||||
self
|
||||
.0
|
||||
|
@ -9,20 +9,20 @@ use flowy_document::manager::{DocumentManager, DocumentSnapshotService, Document
|
||||
use flowy_document_pub::cloud::DocumentCloudService;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_storage::FileStorageService;
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
|
||||
pub struct DocumentDepsResolver();
|
||||
impl DocumentDepsResolver {
|
||||
pub fn resolve(
|
||||
user_manager: Weak<UserManager>,
|
||||
authenticate_user: Weak<AuthenticateUser>,
|
||||
_database_manager: &Arc<DatabaseManager>,
|
||||
collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
cloud_service: Arc<dyn DocumentCloudService>,
|
||||
storage_service: Weak<dyn FileStorageService>,
|
||||
) -> Arc<DocumentManager> {
|
||||
let user_service: Arc<dyn DocumentUserService> =
|
||||
Arc::new(DocumentUserImpl(user_manager.clone()));
|
||||
let snapshot_service = Arc::new(DocumentSnapshotImpl(user_manager));
|
||||
Arc::new(DocumentUserImpl(authenticate_user.clone()));
|
||||
let snapshot_service = Arc::new(DocumentSnapshotImpl(authenticate_user));
|
||||
Arc::new(DocumentManager::new(
|
||||
user_service.clone(),
|
||||
collab_builder,
|
||||
@ -33,10 +33,10 @@ impl DocumentDepsResolver {
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentSnapshotImpl(Weak<UserManager>);
|
||||
struct DocumentSnapshotImpl(Weak<AuthenticateUser>);
|
||||
|
||||
impl DocumentSnapshotImpl {
|
||||
pub fn get_user_manager(&self) -> FlowyResult<Arc<UserManager>> {
|
||||
pub fn get_authenticate_user(&self) -> FlowyResult<Arc<AuthenticateUser>> {
|
||||
self
|
||||
.0
|
||||
.upgrade()
|
||||
@ -49,9 +49,9 @@ impl DocumentSnapshotService for DocumentSnapshotImpl {
|
||||
&self,
|
||||
document_id: &str,
|
||||
) -> FlowyResult<Vec<DocumentSnapshotMeta>> {
|
||||
let user_manager = self.get_user_manager()?;
|
||||
let uid = user_manager.user_id()?;
|
||||
let mut db = user_manager.db_connection(uid)?;
|
||||
let authenticate_user = self.get_authenticate_user()?;
|
||||
let uid = authenticate_user.user_id()?;
|
||||
let mut db = authenticate_user.get_sqlite_connection(uid)?;
|
||||
CollabSnapshotSql::get_all_snapshots(document_id, &mut db).map(|rows| {
|
||||
rows
|
||||
.into_iter()
|
||||
@ -65,9 +65,9 @@ impl DocumentSnapshotService for DocumentSnapshotImpl {
|
||||
}
|
||||
|
||||
fn get_document_snapshot(&self, snapshot_id: &str) -> FlowyResult<DocumentSnapshotData> {
|
||||
let user_manager = self.get_user_manager()?;
|
||||
let uid = user_manager.user_id()?;
|
||||
let mut db = user_manager.db_connection(uid)?;
|
||||
let authenticate_user = self.get_authenticate_user()?;
|
||||
let uid = authenticate_user.user_id()?;
|
||||
let mut db = authenticate_user.get_sqlite_connection(uid)?;
|
||||
CollabSnapshotSql::get_snapshot(snapshot_id, &mut db)
|
||||
.map(|row| DocumentSnapshotData {
|
||||
object_id: row.id,
|
||||
@ -79,7 +79,7 @@ impl DocumentSnapshotService for DocumentSnapshotImpl {
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentUserImpl(Weak<UserManager>);
|
||||
struct DocumentUserImpl(Weak<AuthenticateUser>);
|
||||
impl DocumentUserService for DocumentUserImpl {
|
||||
fn user_id(&self) -> Result<i64, FlowyError> {
|
||||
self
|
||||
@ -97,14 +97,6 @@ impl DocumentUserService for DocumentUserImpl {
|
||||
.workspace_id()
|
||||
}
|
||||
|
||||
fn token(&self) -> Result<Option<String>, FlowyError> {
|
||||
self
|
||||
.0
|
||||
.upgrade()
|
||||
.ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?
|
||||
.token()
|
||||
}
|
||||
|
||||
fn collab_db(&self, uid: i64) -> Result<Weak<CollabKVDB>, FlowyError> {
|
||||
self
|
||||
.0
|
||||
|
@ -1,11 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use collab_integrate::collab_builder::AppFlowyCollabBuilder;
|
||||
use collab_integrate::CollabKVDB;
|
||||
use flowy_database2::entities::DatabaseLayoutPB;
|
||||
@ -21,11 +14,13 @@ use flowy_folder::manager::{FolderManager, FolderUser};
|
||||
use flowy_folder::share::ImportType;
|
||||
use flowy_folder::view_operation::{FolderOperationHandler, FolderOperationHandlers, View};
|
||||
use flowy_folder::ViewLayout;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use flowy_folder_pub::entities::ImportData;
|
||||
use flowy_folder_pub::folder_builder::{ParentChildViews, WorkspaceViewBuilder};
|
||||
use flowy_user::services::data_import::ImportDataSource;
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_folder_pub::folder_builder::WorkspaceViewBuilder;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
|
||||
use crate::integrate::server::ServerProvider;
|
||||
use lib_dispatch::prelude::ToBytes;
|
||||
@ -35,15 +30,14 @@ use lib_infra::future::FutureResult;
|
||||
pub struct FolderDepsResolver();
|
||||
impl FolderDepsResolver {
|
||||
pub async fn resolve(
|
||||
user_manager: Weak<UserManager>,
|
||||
authenticate_user: Weak<AuthenticateUser>,
|
||||
document_manager: &Arc<DocumentManager>,
|
||||
database_manager: &Arc<DatabaseManager>,
|
||||
collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
server_provider: Arc<ServerProvider>,
|
||||
) -> Arc<FolderManager> {
|
||||
let user: Arc<dyn FolderUser> = Arc::new(FolderUserImpl {
|
||||
user_manager: user_manager.clone(),
|
||||
database_manager: Arc::downgrade(database_manager),
|
||||
authenticate_user: authenticate_user.clone(),
|
||||
});
|
||||
|
||||
let handlers = folder_operation_handlers(document_manager.clone(), database_manager.clone());
|
||||
@ -77,67 +71,26 @@ fn folder_operation_handlers(
|
||||
}
|
||||
|
||||
struct FolderUserImpl {
|
||||
user_manager: Weak<UserManager>,
|
||||
database_manager: Weak<DatabaseManager>,
|
||||
authenticate_user: Weak<AuthenticateUser>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl FolderUser for FolderUserImpl {
|
||||
fn user_id(&self) -> Result<i64, FlowyError> {
|
||||
self
|
||||
.user_manager
|
||||
.authenticate_user
|
||||
.upgrade()
|
||||
.ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?
|
||||
.user_id()
|
||||
}
|
||||
|
||||
fn token(&self) -> Result<Option<String>, FlowyError> {
|
||||
self
|
||||
.user_manager
|
||||
.upgrade()
|
||||
.ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?
|
||||
.token()
|
||||
}
|
||||
|
||||
fn collab_db(&self, uid: i64) -> Result<Weak<CollabKVDB>, FlowyError> {
|
||||
self
|
||||
.user_manager
|
||||
.authenticate_user
|
||||
.upgrade()
|
||||
.ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?
|
||||
.get_collab_db(uid)
|
||||
}
|
||||
|
||||
async fn import_appflowy_data_folder(
|
||||
&self,
|
||||
path: &str,
|
||||
container_name: Option<String>,
|
||||
) -> Result<Vec<ParentChildViews>, FlowyError> {
|
||||
match (self.user_manager.upgrade(), self.database_manager.upgrade()) {
|
||||
(Some(user_manager), Some(data_manager)) => {
|
||||
let source = ImportDataSource::AppFlowyDataFolder {
|
||||
path: path.to_string(),
|
||||
container_name,
|
||||
};
|
||||
let import_data = user_manager.import_data_from_source(source).await?;
|
||||
match import_data {
|
||||
ImportData::AppFlowyDataFolder {
|
||||
views,
|
||||
database_view_ids_by_database_id,
|
||||
row_object_ids: _,
|
||||
database_object_ids: _,
|
||||
document_object_ids: _,
|
||||
} => {
|
||||
let _uid = self.user_id()?;
|
||||
data_manager
|
||||
.track_database(database_view_ids_by_database_id)
|
||||
.await?;
|
||||
Ok(views)
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => Err(FlowyError::internal().with_context("Unexpected error: UserSession is None")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentFolderOperation(Arc<DocumentManager>);
|
||||
|
@ -2,6 +2,7 @@ pub use collab_deps::*;
|
||||
pub use database_deps::*;
|
||||
pub use document_deps::*;
|
||||
pub use folder_deps::*;
|
||||
pub use user_deps::*;
|
||||
|
||||
mod collab_deps;
|
||||
mod document_deps;
|
||||
|
@ -1 +1,62 @@
|
||||
use crate::integrate::server::ServerProvider;
|
||||
use collab_integrate::collab_builder::AppFlowyCollabBuilder;
|
||||
use flowy_database2::DatabaseManager;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_folder::manager::FolderManager;
|
||||
use flowy_folder_pub::folder_builder::ParentChildViews;
|
||||
use flowy_sqlite::kv::StorePreferences;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_user_pub::workspace_service::UserWorkspaceService;
|
||||
use lib_infra::async_trait::async_trait;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct UserDepsResolver();
|
||||
|
||||
impl UserDepsResolver {
|
||||
pub async fn resolve(
|
||||
authenticate_user: Arc<AuthenticateUser>,
|
||||
collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
server_provider: Arc<ServerProvider>,
|
||||
store_preference: Arc<StorePreferences>,
|
||||
database_manager: Arc<DatabaseManager>,
|
||||
folder_manager: Arc<FolderManager>,
|
||||
) -> Arc<UserManager> {
|
||||
let workspace_service_impl = Arc::new(UserWorkspaceServiceImpl {
|
||||
database_manager,
|
||||
folder_manager,
|
||||
});
|
||||
UserManager::new(
|
||||
server_provider,
|
||||
store_preference,
|
||||
Arc::downgrade(&collab_builder),
|
||||
authenticate_user,
|
||||
workspace_service_impl,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UserWorkspaceServiceImpl {
|
||||
pub database_manager: Arc<DatabaseManager>,
|
||||
pub folder_manager: Arc<FolderManager>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UserWorkspaceService for UserWorkspaceServiceImpl {
|
||||
async fn did_import_views(&self, views: Vec<ParentChildViews>) -> FlowyResult<()> {
|
||||
self.folder_manager.insert_parent_child_views(views).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn did_import_database_views(
|
||||
&self,
|
||||
ids_by_database_id: HashMap<String, Vec<String>>,
|
||||
) -> FlowyResult<()> {
|
||||
self
|
||||
.database_manager
|
||||
.track_database(ids_by_database_id)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![allow(unused_doc_comments)]
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::RwLock;
|
||||
@ -13,9 +13,9 @@ use flowy_document::manager::DocumentManager;
|
||||
use flowy_folder::manager::FolderManager;
|
||||
use flowy_sqlite::kv::StorePreferences;
|
||||
use flowy_storage::FileStorageService;
|
||||
use flowy_user::services::authenticate_user::AuthenticateUser;
|
||||
use flowy_user::services::entities::UserConfig;
|
||||
use flowy_user::user_manager::UserManager;
|
||||
use flowy_user_pub::cloud::UserCloudServiceProvider;
|
||||
|
||||
use lib_dispatch::prelude::*;
|
||||
use lib_dispatch::runtime::AFPluginRuntime;
|
||||
@ -118,18 +118,23 @@ impl AppFlowyCore {
|
||||
config.device_id.clone(),
|
||||
));
|
||||
|
||||
let user_manager = init_user_manager(
|
||||
&config,
|
||||
&store_preference,
|
||||
server_provider.clone(),
|
||||
Arc::downgrade(&collab_builder),
|
||||
let user_config = UserConfig::new(
|
||||
&config.name,
|
||||
&config.storage_path,
|
||||
&config.application_path,
|
||||
&config.device_id,
|
||||
);
|
||||
|
||||
let authenticate_user = Arc::new(AuthenticateUser::new(
|
||||
user_config.clone(),
|
||||
store_preference.clone(),
|
||||
));
|
||||
|
||||
collab_builder
|
||||
.set_snapshot_persistence(Arc::new(SnapshotDBImpl(Arc::downgrade(&user_manager))));
|
||||
.set_snapshot_persistence(Arc::new(SnapshotDBImpl(Arc::downgrade(&authenticate_user))));
|
||||
|
||||
let database_manager = DatabaseDepsResolver::resolve(
|
||||
Arc::downgrade(&user_manager),
|
||||
Arc::downgrade(&authenticate_user),
|
||||
task_dispatcher.clone(),
|
||||
collab_builder.clone(),
|
||||
server_provider.clone(),
|
||||
@ -137,7 +142,7 @@ impl AppFlowyCore {
|
||||
.await;
|
||||
|
||||
let document_manager = DocumentDepsResolver::resolve(
|
||||
Arc::downgrade(&user_manager),
|
||||
Arc::downgrade(&authenticate_user),
|
||||
&database_manager,
|
||||
collab_builder.clone(),
|
||||
server_provider.clone(),
|
||||
@ -145,7 +150,7 @@ impl AppFlowyCore {
|
||||
);
|
||||
|
||||
let folder_manager = FolderDepsResolver::resolve(
|
||||
Arc::downgrade(&user_manager),
|
||||
Arc::downgrade(&authenticate_user),
|
||||
&document_manager,
|
||||
&database_manager,
|
||||
collab_builder.clone(),
|
||||
@ -153,6 +158,16 @@ impl AppFlowyCore {
|
||||
)
|
||||
.await;
|
||||
|
||||
let user_manager = UserDepsResolver::resolve(
|
||||
authenticate_user,
|
||||
collab_builder.clone(),
|
||||
server_provider.clone(),
|
||||
store_preference.clone(),
|
||||
database_manager.clone(),
|
||||
folder_manager.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
(
|
||||
user_manager,
|
||||
folder_manager,
|
||||
@ -216,26 +231,6 @@ impl AppFlowyCore {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_user_manager(
|
||||
config: &AppFlowyCoreConfig,
|
||||
storage_preference: &Arc<StorePreferences>,
|
||||
user_cloud_service_provider: Arc<dyn UserCloudServiceProvider>,
|
||||
collab_builder: Weak<AppFlowyCollabBuilder>,
|
||||
) -> Arc<UserManager> {
|
||||
let user_config = UserConfig::new(
|
||||
&config.name,
|
||||
&config.storage_path,
|
||||
&config.application_path,
|
||||
&config.device_id,
|
||||
);
|
||||
UserManager::new(
|
||||
user_config,
|
||||
user_cloud_service_provider,
|
||||
storage_preference.clone(),
|
||||
collab_builder,
|
||||
)
|
||||
}
|
||||
|
||||
impl From<Server> for CollabPluginProviderType {
|
||||
fn from(server_type: Server) -> Self {
|
||||
match server_type {
|
||||
|
Reference in New Issue
Block a user