mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 06:37:14 -04:00
chore: create workspace member
This commit is contained in:
parent
4634b51edf
commit
9cd49c2447
13 changed files with 88 additions and 68 deletions
|
@ -27,6 +27,7 @@ class ChatMemberBloc extends Bloc<ChatMemberEvent, ChatMemberState> {
|
|||
final payload = WorkspaceMemberIdPB(
|
||||
uid: Int64.parseInt(userId),
|
||||
);
|
||||
|
||||
await UserEventGetMemberInfo(payload).send().then((result) {
|
||||
result.fold(
|
||||
(member) {
|
||||
|
|
|
@ -244,13 +244,6 @@ class UserBackendService implements IUserBackendService {
|
|||
return UserEventGetWorkspaceSubscriptionInfo(params).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<WorkspaceMemberPB, FlowyError>>
|
||||
getWorkspaceMember() async {
|
||||
final data = WorkspaceMemberIdPB.create()..uid = userId;
|
||||
|
||||
return UserEventGetMemberInfo(data).send();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<FlowyResult<PaymentLinkPB, FlowyError>> createSubscription(
|
||||
String workspaceId,
|
||||
|
|
|
@ -5,6 +5,7 @@ use collab_entity::CollabType;
|
|||
use collab_folder::Folder;
|
||||
use event_integration_test::user_event::use_localhost_af_cloud;
|
||||
use event_integration_test::EventIntegrationTest;
|
||||
use flowy_user::entities::AFRolePB;
|
||||
use flowy_user_pub::entities::AuthType;
|
||||
use std::time::Duration;
|
||||
use tokio::task::LocalSet;
|
||||
|
@ -327,4 +328,10 @@ async fn af_cloud_create_local_workspace_test() {
|
|||
for view in views {
|
||||
test.get_view(&view.id).await;
|
||||
}
|
||||
|
||||
let members = test
|
||||
.get_workspace_members(&created_workspace.workspace_id)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
assert_eq!(members[0].role, AFRolePB::Owner);
|
||||
}
|
||||
|
|
|
@ -2,12 +2,14 @@ use collab_folder::{View, ViewIcon, ViewLayout};
|
|||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::ErrorCode;
|
||||
use flowy_folder_pub::cloud::gen_view_id;
|
||||
use lib_infra::validator_fn::required_not_empty_str;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
use validator::Validate;
|
||||
|
||||
use crate::entities::icon::ViewIconPB;
|
||||
use crate::entities::parser::view::{ViewIdentify, ViewName, ViewThumbnail};
|
||||
|
@ -394,9 +396,10 @@ impl TryInto<CreateViewParams> for CreateOrphanViewPayloadPB {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf, Clone, Debug)]
|
||||
#[derive(Default, ProtoBuf, Validate, Clone, Debug)]
|
||||
pub struct ViewIdPB {
|
||||
#[pb(index = 1)]
|
||||
#[validate(custom(function = "required_not_empty_str"))]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ pub(crate) async fn get_view_handler(
|
|||
folder: AFPluginState<Weak<FolderManager>>,
|
||||
) -> DataResult<ViewPB, FlowyError> {
|
||||
let folder = upgrade_folder(folder)?;
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let view_id = data.try_into_inner()?;
|
||||
let view_pb = folder.get_view_pb(&view_id.value).await?;
|
||||
data_result_ok(view_pb)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use collab_integrate::CollabKVDB;
|
|||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::task::spawn_blocking;
|
||||
use tracing::{event, info, Level};
|
||||
use tracing::{error, event, info, Level};
|
||||
use uuid::Uuid;
|
||||
|
||||
impl FolderManager {
|
||||
|
@ -139,9 +139,12 @@ impl FolderManager {
|
|||
);
|
||||
|
||||
let weak_folder_indexer = Arc::downgrade(&self.folder_indexer);
|
||||
let workspace_id = *workspace_id;
|
||||
tokio::spawn(async move {
|
||||
if let Some(folder_indexer) = weak_folder_indexer.upgrade() {
|
||||
folder_indexer.initialize().await;
|
||||
if let Err(err) = folder_indexer.initialize(&workspace_id).await {
|
||||
error!("Failed to initialize folder indexer: {:?}", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ pub trait IndexManager: Send + Sync {
|
|||
|
||||
#[async_trait]
|
||||
pub trait FolderIndexManager: IndexManager {
|
||||
async fn initialize(&self);
|
||||
async fn initialize(&self, workspace_id: &Uuid) -> Result<(), FlowyError>;
|
||||
|
||||
fn index_all_views(&self, views: Vec<Arc<View>>, workspace_id: Uuid);
|
||||
|
||||
|
|
|
@ -35,8 +35,6 @@ impl Drop for TantivyState {
|
|||
}
|
||||
}
|
||||
|
||||
const FOLDER_INDEX_DIR: &str = "folder_index";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FolderIndexManagerImpl {
|
||||
auth_user: Weak<AuthenticateUser>,
|
||||
|
@ -64,7 +62,7 @@ impl FolderIndexManagerImpl {
|
|||
}
|
||||
|
||||
/// Initializes the state using the workspace directory.
|
||||
async fn initialize(&self) -> FlowyResult<()> {
|
||||
async fn initialize(&self, workspace_id: &Uuid) -> FlowyResult<()> {
|
||||
if let Some(state) = self.state.write().await.take() {
|
||||
info!("Re-initializing folder indexer");
|
||||
drop(state);
|
||||
|
@ -82,7 +80,7 @@ impl FolderIndexManagerImpl {
|
|||
.upgrade()
|
||||
.ok_or_else(|| FlowyError::internal().with_context("AuthenticateUser is not available"))?;
|
||||
|
||||
let index_path = auth_user.get_index_path()?.join(FOLDER_INDEX_DIR);
|
||||
let index_path = auth_user.get_index_path()?.join(workspace_id.to_string());
|
||||
if !index_path.exists() {
|
||||
fs::create_dir_all(&index_path).map_err(|e| {
|
||||
error!("Failed to create folder index directory: {:?}", e);
|
||||
|
@ -327,10 +325,9 @@ impl IndexManager for FolderIndexManagerImpl {
|
|||
|
||||
#[async_trait]
|
||||
impl FolderIndexManager for FolderIndexManagerImpl {
|
||||
async fn initialize(&self) {
|
||||
if let Err(e) = self.initialize().await {
|
||||
error!("Failed to initialize FolderIndexManager: {:?}", e);
|
||||
}
|
||||
async fn initialize(&self, workspace_id: &Uuid) -> Result<(), FlowyError> {
|
||||
self.initialize(workspace_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn index_all_views(&self, views: Vec<Arc<View>>, workspace_id: Uuid) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::af_cloud::define::LoggedUser;
|
||||
use crate::local_server::uid::UserIDGenerator;
|
||||
use anyhow::Context;
|
||||
use client_api::entity::GotrueTokenResponse;
|
||||
use collab::core::origin::CollabOrigin;
|
||||
use collab::preclude::Collab;
|
||||
|
@ -13,10 +14,10 @@ use flowy_error::FlowyError;
|
|||
use flowy_user_pub::cloud::{UserCloudService, UserCollabParams};
|
||||
use flowy_user_pub::entities::*;
|
||||
use flowy_user_pub::sql::{
|
||||
select_all_user_workspace, select_user_profile, select_user_workspace, select_workspace_member,
|
||||
select_workspace_setting, update_user_profile, update_workspace_setting, upsert_workspace_member,
|
||||
upsert_workspace_setting, UserTableChangeset, WorkspaceMemberTable, WorkspaceSettingsChangeset,
|
||||
WorkspaceSettingsTable,
|
||||
insert_local_workspace, select_all_user_workspace, select_user_profile, select_user_workspace,
|
||||
select_workspace_member, select_workspace_setting, update_user_profile, update_workspace_setting,
|
||||
upsert_workspace_member, upsert_workspace_setting, UserTableChangeset, WorkspaceMemberTable,
|
||||
WorkspaceSettingsChangeset, WorkspaceSettingsTable,
|
||||
};
|
||||
use flowy_user_pub::DEFAULT_USER_NAME;
|
||||
use lazy_static::lazy_static;
|
||||
|
@ -161,10 +162,11 @@ impl UserCloudService for LocalServerUserServiceImpl {
|
|||
|
||||
async fn create_workspace(&self, workspace_name: &str) -> Result<UserWorkspace, FlowyError> {
|
||||
let workspace_id = Uuid::new_v4();
|
||||
Ok(UserWorkspace::new_local(
|
||||
workspace_id.to_string(),
|
||||
workspace_name,
|
||||
))
|
||||
let uid = self.logged_user.user_id()?;
|
||||
let mut conn = self.logged_user.get_sqlite_db(uid)?;
|
||||
let user_workspace =
|
||||
insert_local_workspace(uid, &workspace_id.to_string(), workspace_name, &mut conn)?;
|
||||
Ok(user_workspace)
|
||||
}
|
||||
|
||||
async fn patch_workspace(
|
||||
|
@ -180,6 +182,15 @@ impl UserCloudService for LocalServerUserServiceImpl {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_workspace_members(
|
||||
&self,
|
||||
workspace_id: Uuid,
|
||||
) -> Result<Vec<WorkspaceMember>, FlowyError> {
|
||||
let uid = self.logged_user.user_id()?;
|
||||
let member = self.get_workspace_member(&workspace_id, uid).await?;
|
||||
Ok(vec![member])
|
||||
}
|
||||
|
||||
async fn get_user_awareness_doc_state(
|
||||
&self,
|
||||
uid: i64,
|
||||
|
@ -227,15 +238,16 @@ impl UserCloudService for LocalServerUserServiceImpl {
|
|||
Err(err) => {
|
||||
if err.is_record_not_found() {
|
||||
let mut conn = self.logged_user.get_sqlite_db(uid)?;
|
||||
let profile = select_user_profile(uid, &workspace_id.to_string(), &mut conn)?;
|
||||
let profile = select_user_profile(uid, &workspace_id.to_string(), &mut conn)
|
||||
.context("Can't find user profile when create workspace member")?;
|
||||
let row = WorkspaceMemberTable {
|
||||
email: profile.email.to_string(),
|
||||
role: 0,
|
||||
role: Role::Owner as i32,
|
||||
name: profile.name.to_string(),
|
||||
avatar_url: Some(profile.icon_url),
|
||||
uid,
|
||||
workspace_id: workspace_id.to_string(),
|
||||
updated_at: Default::default(),
|
||||
updated_at: chrono::Utc::now().naive_utc(),
|
||||
};
|
||||
|
||||
let member = WorkspaceMember::from(row.clone());
|
||||
|
|
|
@ -231,9 +231,7 @@ pub trait UserCloudService: Send + Sync + 'static {
|
|||
async fn get_workspace_members(
|
||||
&self,
|
||||
workspace_id: Uuid,
|
||||
) -> Result<Vec<WorkspaceMember>, FlowyError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
) -> Result<Vec<WorkspaceMember>, FlowyError>;
|
||||
|
||||
async fn get_user_awareness_doc_state(
|
||||
&self,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::cloud::UserUpdate;
|
||||
use crate::entities::{AuthType, UpdateUserProfileParams, UserProfile};
|
||||
use crate::sql::select_user_workspace;
|
||||
use crate::entities::{AuthType, Role, UpdateUserProfileParams, UserProfile, UserWorkspace};
|
||||
use crate::sql::{
|
||||
select_user_workspace, upsert_user_workspace, upsert_workspace_member, WorkspaceMemberTable,
|
||||
};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sqlite::schema::user_table;
|
||||
use flowy_sqlite::{prelude::*, DBConnection, ExpressionMethods, RunQueryDsl};
|
||||
|
@ -92,6 +94,33 @@ pub fn update_user_profile(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn insert_local_workspace(
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
workspace_name: &str,
|
||||
conn: &mut SqliteConnection,
|
||||
) -> FlowyResult<UserWorkspace> {
|
||||
let user_workspace = UserWorkspace::new_local(workspace_id.to_string(), workspace_name);
|
||||
conn.immediate_transaction(|conn| {
|
||||
let row = select_user_table_row(uid, conn)?;
|
||||
let row = WorkspaceMemberTable {
|
||||
email: row.email,
|
||||
role: Role::Owner as i32,
|
||||
name: row.name,
|
||||
avatar_url: Some(row.icon_url),
|
||||
uid,
|
||||
workspace_id: workspace_id.to_string(),
|
||||
updated_at: chrono::Utc::now().naive_utc(),
|
||||
};
|
||||
|
||||
upsert_user_workspace(uid, AuthType::Local, user_workspace.clone(), conn)?;
|
||||
upsert_workspace_member(conn, row)?;
|
||||
Ok::<_, FlowyError>(())
|
||||
})?;
|
||||
|
||||
Ok(user_workspace)
|
||||
}
|
||||
|
||||
fn select_user_table_row(uid: i64, conn: &mut SqliteConnection) -> Result<UserTable, FlowyError> {
|
||||
let row = user_table::dsl::user_table
|
||||
.filter(user_table::id.eq(&uid.to_string()))
|
||||
|
|
|
@ -147,7 +147,7 @@ pub struct UpdateWorkspaceMemberPB {
|
|||
}
|
||||
|
||||
// Workspace Role
|
||||
#[derive(Debug, ProtoBuf_Enum, Clone, Default)]
|
||||
#[derive(Debug, ProtoBuf_Enum, Clone, Default, Eq, PartialEq)]
|
||||
pub enum AFRolePB {
|
||||
Owner = 0,
|
||||
Member = 1,
|
||||
|
|
|
@ -7,7 +7,6 @@ use arc_swap::ArcSwapOption;
|
|||
use collab::lock::RwLock;
|
||||
use collab_user::core::UserAwareness;
|
||||
use dashmap::DashMap;
|
||||
use flowy_server_pub::AuthenticatorType;
|
||||
use flowy_sqlite::kv::KVStorePreferences;
|
||||
use flowy_sqlite::schema::user_table;
|
||||
use flowy_sqlite::ConnectionPool;
|
||||
|
@ -131,30 +130,15 @@ impl UserManager {
|
|||
let user = self
|
||||
.get_user_profile_from_disk(session.user_id, &session.user_workspace.id)
|
||||
.await?;
|
||||
self.cloud_service.set_server_auth_type(&user.auth_type);
|
||||
|
||||
// Get the current authenticator from the environment variable
|
||||
let env_auth_type = current_authenticator();
|
||||
|
||||
// If the current authenticator is different from the authenticator in the session and it's
|
||||
// not a local authenticator, we need to sign out the user.
|
||||
if user.auth_type != AuthType::Local && user.auth_type != env_auth_type {
|
||||
event!(
|
||||
tracing::Level::INFO,
|
||||
"Auth type changed from {:?} to {:?}",
|
||||
user.auth_type,
|
||||
env_auth_type
|
||||
);
|
||||
self.sign_out().await?;
|
||||
return Ok(());
|
||||
}
|
||||
let auth_type = user.workspace_auth_type;
|
||||
self.cloud_service.set_server_auth_type(&auth_type);
|
||||
|
||||
event!(
|
||||
tracing::Level::INFO,
|
||||
"init user session: {}:{}, auth type: {:?}",
|
||||
user.uid,
|
||||
user.email,
|
||||
user.auth_type,
|
||||
auth_type,
|
||||
);
|
||||
|
||||
self.prepare_user(&session).await;
|
||||
|
@ -253,7 +237,7 @@ impl UserManager {
|
|||
(Ok(collab_db), Ok(sqlite_pool)) => {
|
||||
run_collab_data_migration(
|
||||
&session,
|
||||
&user.auth_type,
|
||||
&auth_type,
|
||||
collab_db,
|
||||
sqlite_pool,
|
||||
self.store_preferences.clone(),
|
||||
|
@ -267,7 +251,7 @@ impl UserManager {
|
|||
self.set_first_time_installed_version();
|
||||
let cloud_config = get_cloud_config(session.user_id, &self.store_preferences);
|
||||
// Init the user awareness. here we ignore the error
|
||||
let _ = self.initial_user_awareness(&session, &user.auth_type).await;
|
||||
let _ = self.initial_user_awareness(&session, &auth_type).await;
|
||||
|
||||
user_status_callback
|
||||
.on_launch_if_authenticated(
|
||||
|
@ -275,7 +259,7 @@ impl UserManager {
|
|||
&cloud_config,
|
||||
&session.user_workspace,
|
||||
&self.authenticate_user.user_config.device_id,
|
||||
&user.auth_type,
|
||||
&auth_type,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
|
@ -357,7 +341,7 @@ impl UserManager {
|
|||
self.save_auth_data(&response, auth_type, &session).await?;
|
||||
|
||||
let _ = self
|
||||
.initial_user_awareness(&session, &user_profile.auth_type)
|
||||
.initial_user_awareness(&session, &user_profile.workspace_auth_type)
|
||||
.await;
|
||||
self
|
||||
.user_status_callback
|
||||
|
@ -556,7 +540,7 @@ impl UserManager {
|
|||
workspace_id: &str,
|
||||
) -> FlowyResult<()> {
|
||||
// If the user is a local user, no need to refresh the user profile
|
||||
if old_user_profile.auth_type.is_local() {
|
||||
if old_user_profile.workspace_auth_type.is_local() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -800,13 +784,6 @@ impl UserManager {
|
|||
}
|
||||
}
|
||||
|
||||
fn current_authenticator() -> AuthType {
|
||||
match AuthenticatorType::from_env() {
|
||||
AuthenticatorType::Local => AuthType::Local,
|
||||
AuthenticatorType::AppFlowyCloud => AuthType::AppFlowyCloud,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upsert_user_profile_change(
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue