From cceee80799cc0fca93ebdf8bb8cb12eaa88fd48a Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Tue, 24 Oct 2023 23:13:51 +0800 Subject: [PATCH] fix: anon user error (#3772) * fix: anon user error * ci: fix tests --- .../lib/core/network_monitor.dart | 4 +- .../appflowy_flutter/lib/startup/startup.dart | 13 +++ .../lib/startup/tasks/app_widget.dart | 3 + .../startup/tasks/appflowy_cloud_task.dart | 14 ++- .../lib/startup/tasks/hot_key.dart | 3 + .../lib/startup/tasks/load_plugin.dart | 3 + .../lib/startup/tasks/localization.dart | 3 + .../startup/tasks/platform_error_catcher.dart | 3 + .../lib/startup/tasks/platform_service.dart | 5 + .../lib/startup/tasks/rust_sdk.dart | 3 + .../lib/startup/tasks/supabase_task.dart | 6 ++ .../lib/startup/tasks/windows.dart | 3 + .../auth/backend_auth_service.dart | 19 ++-- .../user/application/supabase_realtime.dart | 1 + .../settings/widgets/settings_user_view.dart | 2 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 30 ++---- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 32 ++----- frontend/rust-lib/Cargo.toml | 2 +- .../event-integration/src/test_user.rs | 2 +- .../tests/folder/local_test/script.rs | 2 +- .../tests/user/af_cloud_test/test.rs | 11 ++- .../user/local_test/user_profile_test.rs | 29 +++--- .../tests/user/supabase_test/auth_test.rs | 11 --- .../rust-lib/event-integration/tests/util.rs | 15 +-- .../flowy-core/src/integrate/server.rs | 9 +- .../tests/database/database_editor.rs | 8 +- .../filter_test/checklist_filter_test.rs | 7 +- .../af_cloud/impls/user/cloud_service_impl.rs | 28 +----- .../flowy-server/src/af_cloud/server.rs | 2 +- .../src/local_server/impls/user.rs | 21 +++-- .../flowy-server/src/local_server/server.rs | 2 +- .../flowy-server/src/supabase/api/user.rs | 25 +---- .../tests/supabase_test/user_test.rs | 10 +- .../rust-lib/flowy-user-deps/src/cloud.rs | 7 +- .../rust-lib/flowy-user/src/event_handler.rs | 19 ++-- frontend/rust-lib/flowy-user/src/event_map.rs | 6 +- frontend/rust-lib/flowy-user/src/manager.rs | 91 ++++++++++++------- .../rust-lib/flowy-user/src/notification.rs | 1 + 39 files changed, 227 insertions(+), 230 deletions(-) diff --git a/frontend/appflowy_flutter/lib/core/network_monitor.dart b/frontend/appflowy_flutter/lib/core/network_monitor.dart index a7294736aa..42c34de90e 100644 --- a/frontend/appflowy_flutter/lib/core/network_monitor.dart +++ b/frontend/appflowy_flutter/lib/core/network_monitor.dart @@ -27,8 +27,8 @@ class NetworkListener { return _updateConnectionStatus(result); } - void stop() { - _connectivitySubscription.cancel(); + Future stop() async { + await _connectivitySubscription.cancel(); } Future _updateConnectionStatus(ConnectivityResult result) async { diff --git a/frontend/appflowy_flutter/lib/startup/startup.dart b/frontend/appflowy_flutter/lib/startup/startup.dart index d150376b52..37a6fa6bcb 100644 --- a/frontend/appflowy_flutter/lib/startup/startup.dart +++ b/frontend/appflowy_flutter/lib/startup/startup.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:appflowy/workspace/application/settings/prelude.dart'; import 'package:appflowy_backend/appflowy_backend.dart'; +import 'package:appflowy_backend/log.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; @@ -104,6 +105,9 @@ Future initGetIt( config, ), ), + dispose: (launcher) async { + await launcher.dispose(); + }, ); getIt.registerSingleton(PluginSandbox()); @@ -130,6 +134,7 @@ abstract class LaunchTask { LaunchTaskType get type => LaunchTaskType.dataProcessing; Future initialize(LaunchContext context); + Future dispose(); } class AppLauncher { @@ -153,6 +158,14 @@ class AppLauncher { await task.initialize(context); } } + + Future dispose() async { + Log.info('AppLauncher dispose'); + for (final task in tasks) { + await task.dispose(); + } + tasks.clear(); + } } enum IntegrationMode { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/app_widget.dart b/frontend/appflowy_flutter/lib/startup/tasks/app_widget.dart index 6c4e555b7c..3a0e3a71a3 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/app_widget.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/app_widget.dart @@ -86,6 +86,9 @@ class InitAppWidgetTask extends LaunchTask { return; } + + @override + Future dispose() async {} } class ApplicationWidget extends StatefulWidget { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart b/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart index 420c9d93fc..1fd73a6467 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart @@ -1,11 +1,10 @@ import 'package:appflowy/env/env.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/user_auth_listener.dart'; import 'package:appflowy_backend/log.dart'; class InitAppFlowyCloudTask extends LaunchTask { - final _authStateListener = UserAuthStateListener(); + UserAuthStateListener? _authStateListener; bool isLoggingOut = false; @override @@ -13,19 +12,24 @@ class InitAppFlowyCloudTask extends LaunchTask { if (!isAppFlowyCloudEnabled) { return; } + _authStateListener = UserAuthStateListener(); - _authStateListener.start( + _authStateListener?.start( didSignIn: () { isLoggingOut = false; }, onInvalidAuth: (message) async { Log.error(message); - await getIt().signOut(); - // TODO(nathan): Show a dialog to notify the user that the session is expired. if (!isLoggingOut) { await runAppFlowy(); } }, ); } + + @override + Future dispose() async { + await _authStateListener?.stop(); + _authStateListener = null; + } } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/hot_key.dart b/frontend/appflowy_flutter/lib/startup/tasks/hot_key.dart index 7b727a4402..0475d9de77 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/hot_key.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/hot_key.dart @@ -14,4 +14,7 @@ class HotKeyTask extends LaunchTask { } await hotKeyManager.unregisterAll(); } + + @override + Future dispose() async {} } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart index 97e1e6dce9..3b818fa50f 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart @@ -25,4 +25,7 @@ class PluginLoadTask extends LaunchTask { config: CalendarPluginConfig(), ); } + + @override + Future dispose() async {} } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/localization.dart b/frontend/appflowy_flutter/lib/startup/tasks/localization.dart index 1fcb3eb660..83950ffc1b 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/localization.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/localization.dart @@ -10,4 +10,7 @@ class InitLocalizationTask extends LaunchTask { await EasyLocalization.ensureInitialized(); EasyLocalization.logger.enableBuildModes = []; } + + @override + Future dispose() async {} } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/platform_error_catcher.dart b/frontend/appflowy_flutter/lib/startup/tasks/platform_error_catcher.dart index 16dc8ba6da..9d088bb5d4 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/platform_error_catcher.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/platform_error_catcher.dart @@ -18,4 +18,7 @@ class PlatformErrorCatcherTask extends LaunchTask { }; } } + + @override + Future dispose() async {} } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/platform_service.dart b/frontend/appflowy_flutter/lib/startup/tasks/platform_service.dart index 7b76eebf50..6ba03dcb5e 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/platform_service.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/platform_service.dart @@ -11,4 +11,9 @@ class InitPlatformServiceTask extends LaunchTask { Future initialize(LaunchContext context) async { getIt().start(); } + + @override + Future dispose() async { + await getIt().stop(); + } } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart index 90673349c2..11ba1e4e51 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart @@ -27,6 +27,9 @@ class InitRustSDKTask extends LaunchTask { context.getIt().setEnv(env); await context.getIt().init(dir); } + + @override + Future dispose() async {} } AppFlowyEnv getAppFlowyEnv() { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/supabase_task.dart b/frontend/appflowy_flutter/lib/startup/tasks/supabase_task.dart index 8def3d5848..89bc9a7bb1 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/supabase_task.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/supabase_task.dart @@ -54,6 +54,12 @@ class InitSupabaseTask extends LaunchTask { registerProtocolHandler(appflowyDeepLinkSchema); } } + + @override + Future dispose() async { + await realtimeService?.dispose(); + supabase?.dispose(); + } } /// customize the supabase auth storage diff --git a/frontend/appflowy_flutter/lib/startup/tasks/windows.dart b/frontend/appflowy_flutter/lib/startup/tasks/windows.dart index 3e3307dc0f..7b4554b3f5 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/windows.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/windows.dart @@ -71,4 +71,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener { final position = await windowManager.getPosition(); WindowSizeManager().setPosition(position); } + + @override + Future dispose() async {} } diff --git a/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart index b6c287145b..94b5b7dc7a 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart @@ -63,15 +63,22 @@ class BackendAuthService implements AuthService { @override Future> signUpAsGuest({ Map params = const {}, - }) { + }) async { const password = "Guest!@123456"; final uid = uuid(); final userEmail = "$uid@appflowy.io"; - return signUp( - name: LocaleKeys.defaultUsername.tr(), - password: password, - email: userEmail, - ); + + final request = SignUpPayloadPB.create() + ..name = LocaleKeys.defaultUsername.tr() + ..email = userEmail + ..password = password + // When sign up as guest, the auth type is always local. + ..authType = AuthTypePB.Local + ..deviceId = await getDeviceId(); + final response = await UserEventSignUp(request).send().then( + (value) => value.swap(), + ); + return response; } @override diff --git a/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart b/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart index b708a03e9f..c71869ab2a 100644 --- a/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart +++ b/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart @@ -36,6 +36,7 @@ class SupbaseRealtimeService { isLoggingOut = false; }, onInvalidAuth: (message) async { + Log.error(message); await getIt().signOut(); channel?.unsubscribe(); channel = null; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_user_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_user_view.dart index 00f15c9ab9..ee15bfbc31 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_user_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_user_view.dart @@ -54,7 +54,7 @@ class SettingsUserView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ _buildUserIconSetting(context), - if (isCloudEnabled) ...[ + if (isCloudEnabled && user.authType != AuthTypePB.Local) ...[ const VSpace(12), UserEmailInput(user.email) ], diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 417a4d21a4..9a0d84a591 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "bytes", @@ -1292,7 +1292,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1438,7 +1438,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "chrono", @@ -2781,7 +2781,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "futures-util", @@ -2797,7 +2797,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "jsonwebtoken", @@ -3232,7 +3232,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "reqwest", @@ -4307,7 +4307,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -4399,19 +4398,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.29", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4915,7 +4901,7 @@ dependencies = [ [[package]] name = "realtime-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "bytes", "collab", @@ -5637,7 +5623,7 @@ dependencies = [ [[package]] name = "shared_entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "collab-entity", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 71833a1417..71d703367a 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -38,7 +38,7 @@ custom-protocol = ["tauri/custom-protocol"] # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "141354bfa9d08c387cf9beb9697b89b052790e89" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc6b451104e7154b38df5ae9c4e7215a61fcf172" } # Please use the following script to update collab. # Working directory: frontend # diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 591e3240e6..7115bac4ec 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -660,7 +660,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "bytes", @@ -1138,7 +1138,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1265,7 +1265,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "chrono", @@ -2440,7 +2440,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "futures-util", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "jsonwebtoken", @@ -2816,7 +2816,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "reqwest", @@ -3623,7 +3623,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3643,7 +3643,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3711,19 +3710,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.31", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4265,7 +4251,7 @@ dependencies = [ [[package]] name = "realtime-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "bytes", "collab", @@ -4886,7 +4872,7 @@ dependencies = [ [[package]] name = "shared_entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=141354bfa9d08c387cf9beb9697b89b052790e89#141354bfa9d08c387cf9beb9697b89b052790e89" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc6b451104e7154b38df5ae9c4e7215a61fcf172#cc6b451104e7154b38df5ae9c4e7215a61fcf172" dependencies = [ "anyhow", "collab-entity", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 9f3142145e..8f07b4df8f 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -82,7 +82,7 @@ incremental = false # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "141354bfa9d08c387cf9beb9697b89b052790e89" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc6b451104e7154b38df5ae9c4e7215a61fcf172" } # Please use the following script to update collab. # Working directory: frontend # diff --git a/frontend/rust-lib/event-integration/src/test_user.rs b/frontend/rust-lib/event-integration/src/test_user.rs index b09c4b9acc..9d03b8f1e8 100644 --- a/frontend/rust-lib/event-integration/src/test_user.rs +++ b/frontend/rust-lib/event-integration/src/test_user.rs @@ -107,7 +107,7 @@ impl EventIntegrationTest { *self.auth_type.write() = auth_type; } - pub async fn init_user(&self) -> UserProfilePB { + pub async fn init_anon_user(&self) -> UserProfilePB { self.sign_up_as_guest().await.user_profile } diff --git a/frontend/rust-lib/event-integration/tests/folder/local_test/script.rs b/frontend/rust-lib/event-integration/tests/folder/local_test/script.rs index 24c56d8f42..09a11a94f8 100644 --- a/frontend/rust-lib/event-integration/tests/folder/local_test/script.rs +++ b/frontend/rust-lib/event-integration/tests/folder/local_test/script.rs @@ -76,7 +76,7 @@ pub struct FolderTest { impl FolderTest { pub async fn new() -> Self { let sdk = EventIntegrationTest::new(); - let _ = sdk.init_user().await; + let _ = sdk.init_anon_user().await; let workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; let parent_view = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; let view = create_view( diff --git a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/test.rs b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/test.rs index e0a138e0fa..a37eaa1276 100644 --- a/frontend/rust-lib/event-integration/tests/user/af_cloud_test/test.rs +++ b/frontend/rust-lib/event-integration/tests/user/af_cloud_test/test.rs @@ -14,7 +14,7 @@ async fn af_cloud_sign_up_test() { } #[tokio::test] -async fn af_cloud_update_user_metadata_of_open_ai_key() { +async fn af_cloud_update_user_metadata() { if get_af_cloud_config().is_some() { let test = EventIntegrationTest::new(); let user = test.af_cloud_sign_up().await; @@ -25,12 +25,17 @@ async fn af_cloud_update_user_metadata_of_open_ai_key() { test .update_user_profile(UpdateUserProfilePayloadPB { id: user.id, - openai_key: Some("new openai_key".to_string()), + openai_key: Some("new openai key".to_string()), + stability_ai_key: Some("new stability ai key".to_string()), ..Default::default() }) .await; let new_profile = test.get_user_profile().await.unwrap(); - assert_eq!(new_profile.openai_key, "new openai_key".to_string()); + assert_eq!(new_profile.openai_key, "new openai key".to_string()); + assert_eq!( + new_profile.stability_ai_key, + "new stability ai key".to_string() + ); } } diff --git a/frontend/rust-lib/event-integration/tests/user/local_test/user_profile_test.rs b/frontend/rust-lib/event-integration/tests/user/local_test/user_profile_test.rs index a488de02a1..60f5cc84cc 100644 --- a/frontend/rust-lib/event-integration/tests/user/local_test/user_profile_test.rs +++ b/frontend/rust-lib/event-integration/tests/user/local_test/user_profile_test.rs @@ -1,7 +1,7 @@ use nanoid::nanoid; use event_integration::{event_builder::EventBuilder, EventIntegrationTest}; -use flowy_user::entities::{UpdateUserProfilePayloadPB, UserProfilePB}; +use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB, UserProfilePB}; use flowy_user::{errors::ErrorCode, event_map::UserEvent::*}; use crate::user::local_test::helper::*; @@ -20,20 +20,24 @@ async fn user_profile_get_failed() { } #[tokio::test] -async fn user_profile_get() { +async fn anon_user_profile_get() { let test = EventIntegrationTest::new(); - let user_profile = test.init_user().await; + let user_profile = test.init_anon_user().await; let user = EventBuilder::new(test.clone()) .event(GetUserProfile) .sync_send() .parse::(); - assert_eq!(user_profile, user); + assert_eq!(user_profile.id, user.id); + assert_eq!(user_profile.openai_key, user.openai_key); + assert_eq!(user_profile.stability_ai_key, user.stability_ai_key); + assert_eq!(user_profile.workspace_id, user.workspace_id); + assert_eq!(user_profile.auth_type, AuthTypePB::Local); } #[tokio::test] async fn user_update_with_name() { let sdk = EventIntegrationTest::new(); - let user = sdk.init_user().await; + let user = sdk.init_anon_user().await; let new_name = "hello_world".to_owned(); let request = UpdateUserProfilePayloadPB::new(user.id).name(&new_name); let _ = EventBuilder::new(sdk.clone()) @@ -52,7 +56,7 @@ async fn user_update_with_name() { #[tokio::test] async fn user_update_with_ai_key() { let sdk = EventIntegrationTest::new(); - let user = sdk.init_user().await; + let user = sdk.init_anon_user().await; let openai_key = "openai_key".to_owned(); let stability_ai_key = "stability_ai_key".to_owned(); let request = UpdateUserProfilePayloadPB::new(user.id) @@ -73,9 +77,9 @@ async fn user_update_with_ai_key() { } #[tokio::test] -async fn user_update_with_email() { +async fn anon_user_update_with_email() { let sdk = EventIntegrationTest::new(); - let user = sdk.init_user().await; + let user = sdk.init_anon_user().await; let new_email = format!("{}@gmail.com", nanoid!(6)); let request = UpdateUserProfilePayloadPB::new(user.id).email(&new_email); let _ = EventBuilder::new(sdk.clone()) @@ -87,13 +91,14 @@ async fn user_update_with_email() { .sync_send() .parse::(); - assert_eq!(user_profile.email, new_email,); + // When the user is anonymous, the email is empty no matter what you set + assert!(user_profile.email.is_empty()); } #[tokio::test] async fn user_update_with_invalid_email() { let test = EventIntegrationTest::new(); - let user = test.init_user().await; + let user = test.init_anon_user().await; for email in invalid_email_test_case() { let request = UpdateUserProfilePayloadPB::new(user.id).email(&email); assert_eq!( @@ -112,7 +117,7 @@ async fn user_update_with_invalid_email() { #[tokio::test] async fn user_update_with_invalid_password() { let test = EventIntegrationTest::new(); - let user = test.init_user().await; + let user = test.init_anon_user().await; for password in invalid_password_test_case() { let request = UpdateUserProfilePayloadPB::new(user.id).password(&password); @@ -129,7 +134,7 @@ async fn user_update_with_invalid_password() { #[tokio::test] async fn user_update_with_invalid_name() { let test = EventIntegrationTest::new(); - let user = test.init_user().await; + let user = test.init_anon_user().await; let request = UpdateUserProfilePayloadPB::new(user.id).name(""); assert!(EventBuilder::new(test.clone()) .event(UpdateUserProfile) diff --git a/frontend/rust-lib/event-integration/tests/user/supabase_test/auth_test.rs b/frontend/rust-lib/event-integration/tests/user/supabase_test/auth_test.rs index 999df506ef..d2bf889a83 100644 --- a/frontend/rust-lib/event-integration/tests/user/supabase_test/auth_test.rs +++ b/frontend/rust-lib/event-integration/tests/user/supabase_test/auth_test.rs @@ -194,17 +194,6 @@ async fn sign_up_as_guest_and_then_update_to_existing_cloud_user_test() { } } -#[tokio::test] -async fn check_not_exist_user_test() { - if let Some(test) = FlowySupabaseTest::new() { - let err = test - .check_user_with_uuid(&uuid::Uuid::new_v4().to_string()) - .await - .unwrap_err(); - assert_eq!(err.code, ErrorCode::RecordNotFound); - } -} - #[tokio::test] async fn get_user_profile_test() { if let Some(test) = FlowySupabaseTest::new() { diff --git a/frontend/rust-lib/event-integration/tests/util.rs b/frontend/rust-lib/event-integration/tests/util.rs index 9847095458..37a2b20616 100644 --- a/frontend/rust-lib/event-integration/tests/util.rs +++ b/frontend/rust-lib/event-integration/tests/util.rs @@ -23,7 +23,7 @@ use flowy_server::supabase::api::*; use flowy_server::{AppFlowyEncryption, EncryptionImpl}; use flowy_server_config::af_cloud_config::AFCloudConfiguration; use flowy_server_config::supabase_config::SupabaseConfiguration; -use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB, UserCredentialsPB}; +use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB}; use flowy_user::errors::FlowyError; use flowy_user::event_map::UserCloudServiceProvider; use flowy_user::event_map::UserEvent::*; @@ -49,19 +49,6 @@ impl FlowySupabaseTest { Some(Self { inner: test }) } - pub async fn check_user_with_uuid(&self, uuid: &str) -> Result<(), FlowyError> { - match EventBuilder::new(self.inner.clone()) - .event(CheckUser) - .payload(UserCredentialsPB::from_uuid(uuid)) - .async_send() - .await - .error() - { - None => Ok(()), - Some(error) => Err(error), - } - } - pub async fn update_user_profile( &self, payload: UpdateUserProfilePayloadPB, diff --git a/frontend/rust-lib/flowy-core/src/integrate/server.rs b/frontend/rust-lib/flowy-core/src/integrate/server.rs index 2895582230..418890fce5 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/server.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/server.rs @@ -91,6 +91,11 @@ impl ServerProvider { } pub fn set_server_type(&self, server_type: ServerType) { + let old_server_type = self.server_type.read().clone(); + if server_type != old_server_type { + self.providers.write().remove(&old_server_type); + } + *self.server_type.write() = server_type; } @@ -179,9 +184,9 @@ struct LocalServerDBImpl { } impl LocalServerDB for LocalServerDBImpl { - fn get_user_profile(&self, uid: i64) -> Result, FlowyError> { + fn get_user_profile(&self, uid: i64) -> Result { let sqlite_db = open_user_db(&self.storage_path, uid)?; - let user_profile = get_user_profile(&sqlite_db, uid).ok(); + let user_profile = get_user_profile(&sqlite_db, uid)?; Ok(user_profile) } diff --git a/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs b/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs index 9fe298be3d..4d0a836332 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs @@ -38,7 +38,7 @@ pub struct DatabaseEditorTest { impl DatabaseEditorTest { pub async fn new_grid() -> Self { let sdk = EventIntegrationTest::new(); - let _ = sdk.init_user().await; + let _ = sdk.init_anon_user().await; let params = make_test_grid(); let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await; @@ -47,7 +47,7 @@ impl DatabaseEditorTest { pub async fn new_no_date_grid() -> Self { let sdk = EventIntegrationTest::new(); - let _ = sdk.init_user().await; + let _ = sdk.init_anon_user().await; let params = make_no_date_test_grid(); let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await; @@ -56,7 +56,7 @@ impl DatabaseEditorTest { pub async fn new_board() -> Self { let sdk = EventIntegrationTest::new(); - let _ = sdk.init_user().await; + let _ = sdk.init_anon_user().await; let params = make_test_board(); let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await; @@ -65,7 +65,7 @@ impl DatabaseEditorTest { pub async fn new_calendar() -> Self { let sdk = EventIntegrationTest::new(); - let _ = sdk.init_user().await; + let _ = sdk.init_anon_user().await; let params = make_test_calendar(); let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await; diff --git a/frontend/rust-lib/flowy-database2/tests/database/filter_test/checklist_filter_test.rs b/frontend/rust-lib/flowy-database2/tests/database/filter_test/checklist_filter_test.rs index b8abeeca9c..b79042a83c 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/filter_test/checklist_filter_test.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/filter_test/checklist_filter_test.rs @@ -58,10 +58,9 @@ async fn get_checklist_cell_options(test: &DatabaseFilterTest) -> Vec { .get_cell(&field.id, &test.row_details[0].row.id) .await; row_cell - .map_or_else( - || ChecklistCellData::default(), - |cell| ChecklistCellData::from(&cell), - ) + .map_or(ChecklistCellData::default(), |cell| { + ChecklistCellData::from(&cell) + }) .options .into_iter() .map(|option| option.id) 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 b5d090df87..54476dbea8 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 @@ -102,15 +102,14 @@ where fn get_user_profile( &self, _credential: UserCredentials, - ) -> FutureResult, FlowyError> { + ) -> FutureResult { let try_get_client = self.server.try_get_client(); FutureResult::new(async move { let client = try_get_client?; let profile = client.get_profile().await?; let token = client.get_token()?; let profile = user_profile_from_af_profile(token, profile)?; - - Ok(Some(profile)) + Ok(profile) }) } @@ -122,29 +121,6 @@ where }) } - fn check_user(&self, credential: UserCredentials) -> FutureResult<(), Error> { - let try_get_client = self.server.try_get_client(); - FutureResult::new(async move { - // from params - let token = credential.token.ok_or(anyhow!("expecting token"))?; - let uid = credential.uid.ok_or(anyhow!("expecting uid"))?; - - // from cloud - let client = try_get_client?; - let profile = client.get_profile().await?; - let client_token = client.access_token()?; - - // compare and check - if uid != profile.uid { - return Err(anyhow!("uid mismatch")); - } - if token != client_token { - return Err(anyhow!("token mismatch")); - } - Ok(()) - }) - } - fn add_workspace_member( &self, user_email: String, diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs index 47160e6394..f2257586b8 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs @@ -86,7 +86,7 @@ impl AppFlowyServer for AFCloudServer { fn set_token(&self, token: &str) -> Result<(), Error> { self .client - .set_token(token) + .restore_token(token) .map_err(|err| Error::new(FlowyError::unauthorized().with_context(err))) } diff --git a/frontend/rust-lib/flowy-server/src/local_server/impls/user.rs b/frontend/rust-lib/flowy-server/src/local_server/impls/user.rs index 5cc0455ac1..e8400b9a16 100644 --- a/frontend/rust-lib/flowy-server/src/local_server/impls/user.rs +++ b/frontend/rust-lib/flowy-server/src/local_server/impls/user.rs @@ -102,21 +102,24 @@ impl UserCloudService for LocalServerUserAuthServiceImpl { FutureResult::new(async { Ok(()) }) } - fn get_user_profile( - &self, - _credential: UserCredentials, - ) -> FutureResult, FlowyError> { - FutureResult::new(async { Ok(None) }) + fn get_user_profile(&self, credential: UserCredentials) -> FutureResult { + let result = match credential.uid { + None => Err(FlowyError::record_not_found()), + Some(uid) => { + self.db.get_user_profile(uid).map(|mut profile| { + // We don't want to expose the email in the local server + profile.email = "".to_string(); + profile + }) + }, + }; + FutureResult::new(async { result }) } fn get_all_user_workspaces(&self, _uid: i64) -> FutureResult, Error> { FutureResult::new(async { Ok(vec![]) }) } - fn check_user(&self, _credential: UserCredentials) -> FutureResult<(), Error> { - FutureResult::new(async { Ok(()) }) - } - fn add_workspace_member( &self, _user_email: String, diff --git a/frontend/rust-lib/flowy-server/src/local_server/server.rs b/frontend/rust-lib/flowy-server/src/local_server/server.rs index 17ec06f4ed..af300a6e69 100644 --- a/frontend/rust-lib/flowy-server/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-server/src/local_server/server.rs @@ -21,7 +21,7 @@ use crate::local_server::impls::{ use crate::AppFlowyServer; pub trait LocalServerDB: Send + Sync + 'static { - fn get_user_profile(&self, uid: i64) -> Result, FlowyError>; + fn get_user_profile(&self, uid: i64) -> Result; fn get_user_workspace(&self, uid: i64) -> Result, FlowyError>; fn get_collab_updates(&self, uid: i64, object_id: &str) -> Result>, FlowyError>; } diff --git a/frontend/rust-lib/flowy-server/src/supabase/api/user.rs b/frontend/rust-lib/flowy-server/src/supabase/api/user.rs index 69581d69f0..f1b138596d 100644 --- a/frontend/rust-lib/flowy-server/src/supabase/api/user.rs +++ b/frontend/rust-lib/flowy-server/src/supabase/api/user.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use std::future::Future; use std::iter::Take; use std::pin::Pin; -use std::str::FromStr; use std::sync::{Arc, Weak}; use std::time::Duration; @@ -199,10 +198,7 @@ where }) } - fn get_user_profile( - &self, - credential: UserCredentials, - ) -> FutureResult, FlowyError> { + fn get_user_profile(&self, credential: UserCredentials) -> FutureResult { let try_get_postgrest = self.server.try_get_postgrest(); let uid = credential .uid @@ -212,8 +208,8 @@ where let postgrest = try_get_postgrest?; let user_profile_resp = get_user_profile(postgrest, GetUserProfileParams::Uid(uid)).await?; match user_profile_resp { - None => Ok(None), - Some(response) => Ok(Some(UserProfile { + None => Err(FlowyError::record_not_found()), + Some(response) => Ok(UserProfile { uid: response.uid, email: response.email, name: response.name, @@ -225,7 +221,7 @@ where auth_type: AuthType::Supabase, encryption_type: EncryptionType::from_sign(&response.encryption_sign), updated_at: response.updated_at.timestamp(), - })), + }), } }) } @@ -238,18 +234,6 @@ where Ok(user_workspaces) }) } - - fn check_user(&self, credential: UserCredentials) -> FutureResult<(), Error> { - let try_get_postgrest = self.server.try_get_postgrest(); - let uuid = credential.uuid.and_then(|uuid| Uuid::from_str(&uuid).ok()); - let uid = credential.uid; - FutureResult::new(async move { - let postgrest = try_get_postgrest?; - check_user(postgrest, uid, uuid).await?; - Ok(()) - }) - } - fn add_workspace_member( &self, _user_email: String, @@ -512,6 +496,7 @@ async fn update_user_profile( Ok(()) } +#[allow(dead_code)] async fn check_user( postgrest: Arc, uid: Option, diff --git a/frontend/rust-lib/flowy-server/tests/supabase_test/user_test.rs b/frontend/rust-lib/flowy-server/tests/supabase_test/user_test.rs index b2de79ada6..07293e4a0b 100644 --- a/frontend/rust-lib/flowy-server/tests/supabase_test/user_test.rs +++ b/frontend/rust-lib/flowy-server/tests/supabase_test/user_test.rs @@ -1,6 +1,7 @@ use uuid::Uuid; use flowy_encrypt::{encrypt_text, generate_encryption_secret}; +use flowy_error::FlowyError; use flowy_user_deps::entities::*; use lib_infra::box_any::BoxAny; @@ -66,7 +67,6 @@ async fn supabase_update_user_profile_test() { let user_profile = user_service .get_user_profile(UserCredentials::from_uid(user.user_id)) .await - .unwrap() .unwrap(); assert_eq!(user_profile.name, "123"); @@ -89,7 +89,6 @@ async fn supabase_get_user_profile_test() { user_service .get_user_profile(credential.clone()) .await - .unwrap() .unwrap(); } @@ -100,12 +99,12 @@ async fn supabase_get_not_exist_user_profile_test() { } let user_service = user_auth_service(); - let result = user_service + let result: FlowyError = user_service .get_user_profile(UserCredentials::from_uid(i64::MAX)) .await - .unwrap(); + .unwrap_err(); // user not found - assert!(result.is_none()); + assert!(result.is_record_not_found()); } #[tokio::test] @@ -134,7 +133,6 @@ async fn user_encryption_sign_test() { let user_profile: UserProfile = user_service .get_user_profile(UserCredentials::from_uid(user.user_id)) .await - .unwrap() .unwrap(); assert_eq!( user_profile.encryption_type, diff --git a/frontend/rust-lib/flowy-user-deps/src/cloud.rs b/frontend/rust-lib/flowy-user-deps/src/cloud.rs index bb50d388af..7eae820582 100644 --- a/frontend/rust-lib/flowy-user-deps/src/cloud.rs +++ b/frontend/rust-lib/flowy-user-deps/src/cloud.rs @@ -89,16 +89,11 @@ pub trait UserCloudService: Send + Sync + 'static { /// Get the user information using the user's token or uid /// return None if the user is not found - fn get_user_profile( - &self, - credential: UserCredentials, - ) -> FutureResult, FlowyError>; + fn get_user_profile(&self, credential: UserCredentials) -> FutureResult; /// Return the all the workspaces of the user fn get_all_user_workspaces(&self, uid: i64) -> FutureResult, Error>; - fn check_user(&self, credential: UserCredentials) -> FutureResult<(), Error>; - fn add_workspace_member( &self, user_email: String, diff --git a/frontend/rust-lib/flowy-user/src/event_handler.rs b/frontend/rust-lib/flowy-user/src/event_handler.rs index 4e07732603..80dcd98fef 100644 --- a/frontend/rust-lib/flowy-user/src/event_handler.rs +++ b/frontend/rust-lib/flowy-user/src/event_handler.rs @@ -82,30 +82,29 @@ pub async fn init_user_handler( } #[tracing::instrument(level = "debug", skip(manager))] -pub async fn check_user_handler( - manager: AFPluginState>, -) -> Result<(), FlowyError> { - let manager = upgrade_manager(manager)?; - manager.check_user().await?; - Ok(()) -} - -#[tracing::instrument(level = "debug", skip(manager), err)] pub async fn get_user_profile_handler( manager: AFPluginState>, ) -> DataResult { let manager = upgrade_manager(manager)?; let uid = manager.get_session()?.user_id; - let user_profile = manager.get_user_profile(uid).await?; + let mut user_profile = manager.get_user_profile(uid).await?; let weak_manager = Arc::downgrade(&manager); let cloned_user_profile = user_profile.clone(); + + // Refresh the user profile in the background tokio::spawn(async move { if let Some(manager) = weak_manager.upgrade() { let _ = manager.refresh_user_profile(&cloned_user_profile).await; } }); + // When the user is logged in with a local account, the email field is a placeholder and should + // not be exposed to the client. So we set the email field to an empty string. + if user_profile.auth_type == AuthType::Local { + user_profile.email = "".to_string(); + } + event!( tracing::Level::DEBUG, "Get user profile: {:?}", diff --git a/frontend/rust-lib/flowy-user/src/event_map.rs b/frontend/rust-lib/flowy-user/src/event_map.rs index 3fc698593a..40ade230e2 100644 --- a/frontend/rust-lib/flowy-user/src/event_map.rs +++ b/frontend/rust-lib/flowy-user/src/event_map.rs @@ -30,7 +30,6 @@ pub fn init(user_session: Weak) -> AFPlugin { .event(UserEvent::GetUserProfile, get_user_profile_handler) .event(UserEvent::SignOut, sign_out) .event(UserEvent::UpdateUserProfile, update_user_profile_handler) - .event(UserEvent::CheckUser, check_user_handler) .event(UserEvent::SetAppearanceSetting, set_appearance_setting) .event(UserEvent::GetAppearanceSetting, get_appearance_setting) .event(UserEvent::GetUserSetting, get_user_setting) @@ -232,11 +231,8 @@ pub enum UserEvent { #[event(output = "UserProfilePB")] GetUserProfile = 4, - /// Check the user current session is valid or not - #[event(output = "UserProfilePB")] - CheckUser = 5, - /// Initialize resources for the current user after launching the application + /// #[event()] InitUser = 6, diff --git a/frontend/rust-lib/flowy-user/src/manager.rs b/frontend/rust-lib/flowy-user/src/manager.rs index 7fe83d3ec1..4fb483e6e9 100644 --- a/frontend/rust-lib/flowy-user/src/manager.rs +++ b/frontend/rust-lib/flowy-user/src/manager.rs @@ -97,7 +97,7 @@ impl UserManager { while let Ok(update) = rx.recv().await { if let Some(user_manager) = weak_user_manager.upgrade() { if let Err(err) = user_manager.handler_user_update(update).await { - tracing::error!("handler_user_update failed: {:?}", err); + error!("handler_user_update failed: {:?}", err); } } } @@ -172,10 +172,10 @@ impl UserManager { info!("Did apply migrations: {:?}", applied_migrations); } }, - Err(e) => tracing::error!("User data migration failed: {:?}", e), + Err(e) => error!("User data migration failed: {:?}", e), } }, - _ => tracing::error!("Failed to get collab db or sqlite pool"), + _ => error!("Failed to get collab db or sqlite pool"), } self.set_collab_config(&session); // Init the user awareness @@ -193,7 +193,7 @@ impl UserManager { ) .await { - tracing::error!("Failed to call did_init callback: {:?}", e); + error!("Failed to call did_init callback: {:?}", e); } } *self.user_status_callback.write().await = Arc::new(user_status_callback); @@ -253,7 +253,7 @@ impl UserManager { .did_sign_in(user_profile.uid, &latest_workspace, &session.device_id) .await { - tracing::error!("Failed to call did_sign_in callback: {:?}", e); + error!("Failed to call did_sign_in callback: {:?}", e); } send_auth_state_notification(AuthStateChangedPB { state: AuthStatePB::AuthStateSignIn, @@ -349,7 +349,6 @@ impl UserManager { UserAwarenessDataSource::Remote }; - event!(tracing::Level::DEBUG, "Sign up response: {:?}", response); if response.is_new_user { if let Some(old_user) = migration_user { let new_user = MigrationUser { @@ -403,9 +402,8 @@ impl UserManager { let server = self.cloud_services.get_user_service()?; tokio::spawn(async move { - match server.sign_out(None).await { - Ok(_) => {}, - Err(e) => event!(tracing::Level::ERROR, "{:?}", e), + if let Err(err) = server.sign_out(None).await { + event!(tracing::Level::ERROR, "{:?}", err); } }); Ok(()) @@ -437,15 +435,6 @@ impl UserManager { Ok(()) } - pub async fn check_user(&self) -> Result<(), FlowyError> { - let user_id = self.get_session()?.user_id; - let user = self.get_user_profile(user_id).await?; - let credential = UserCredentials::new(Some(user.token), Some(user_id), None); - let auth_service = self.cloud_services.get_user_service()?; - auth_service.check_user(credential).await?; - Ok(()) - } - /// Fetches the user profile for the given user ID. pub async fn get_user_profile(&self, uid: i64) -> Result { let user: UserProfile = user_table::dsl::user_table @@ -457,27 +446,63 @@ impl UserManager { } #[tracing::instrument(level = "info", skip_all)] - pub async fn refresh_user_profile( - &self, - old_user_profile: &UserProfile, - ) -> FlowyResult { + pub async fn refresh_user_profile(&self, old_user_profile: &UserProfile) -> FlowyResult<()> { let uid = old_user_profile.uid; - let new_user_profile: UserProfile = self + let result: Result = self .cloud_services .get_user_service()? .get_user_profile(UserCredentials::from_uid(uid)) - .await? - .ok_or_else(|| FlowyError::new(ErrorCode::RecordNotFound, "User not found"))?; + .await; - if new_user_profile.updated_at > old_user_profile.updated_at { - check_encryption_sign(old_user_profile, &new_user_profile.encryption_type.sign()); + match result { + Ok(new_user_profile) => { + // If the authentication type has changed, it indicates that the user has signed in + // using a different release package but is sharing the same data folder. + // In such cases, notify the frontend to log out. + if old_user_profile.auth_type != AuthType::Local + && new_user_profile.auth_type != old_user_profile.auth_type + { + event!( + tracing::Level::INFO, + "User login with different cloud: {:?} -> {:?}", + old_user_profile.auth_type, + new_user_profile.auth_type + ); - // Save the new user profile - let changeset = UserTableChangeset::from_user_profile(new_user_profile.clone()); - let _ = upsert_user_profile_change(uid, self.database.get_pool(uid)?, changeset); + send_auth_state_notification(AuthStateChangedPB { + state: AuthStatePB::InvalidAuth, + message: "User login with different cloud".to_string(), + }) + .send(); + return Ok(()); + } + + // If the user profile is updated, save the new user profile + if new_user_profile.updated_at > old_user_profile.updated_at { + check_encryption_sign(old_user_profile, &new_user_profile.encryption_type.sign()); + // Save the new user profile + let changeset = UserTableChangeset::from_user_profile(new_user_profile); + let _ = upsert_user_profile_change(uid, self.database.get_pool(uid)?, changeset); + } + Ok(()) + }, + Err(err) => { + // If the user is not found, notify the frontend to logout + if err.is_record_not_found() { + event!( + tracing::Level::INFO, + "User is not found on the server when refreshing profile" + ); + + send_auth_state_notification(AuthStateChangedPB { + state: AuthStatePB::InvalidAuth, + message: "User is not found on the server".to_string(), + }) + .send(); + } + Err(err) + }, } - - Ok(new_user_profile) } pub fn user_dir(&self, uid: i64) -> String { @@ -680,7 +705,7 @@ impl UserManager { ) .await { - tracing::error!("Sync user data to cloud failed: {:?}", err); + error!("Sync user data to cloud failed: {:?}", err); } // Save the old user workspace setting. diff --git a/frontend/rust-lib/flowy-user/src/notification.rs b/frontend/rust-lib/flowy-user/src/notification.rs index b3d15ba19c..bf020f5a06 100644 --- a/frontend/rust-lib/flowy-user/src/notification.rs +++ b/frontend/rust-lib/flowy-user/src/notification.rs @@ -26,6 +26,7 @@ pub(crate) fn send_notification(id: &str, ty: UserNotification) -> NotificationB NotificationBuilder::new(id, ty, USER_OBSERVABLE_SOURCE) } +#[tracing::instrument(level = "trace")] pub(crate) fn send_auth_state_notification(payload: AuthStateChangedPB) -> NotificationBuilder { NotificationBuilder::new( "auth_state_change_notification",