fix: token refresh on local (#4650)

* fix: refresh user token on local

* chore: add test
This commit is contained in:
Nathan.fooo 2024-02-14 09:38:05 +08:00 committed by GitHub
parent b356927e60
commit e81a2ff577
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 126 additions and 43 deletions

View File

@ -1,5 +1,5 @@
# Release Notes # Release Notes
## Version 0.4.7 - 02/08/2024 ## Version 0.4.8 - 02/13/2024
### Bug Fixes ### Bug Fixes
- Fixed a possible error when loading workspaces - Fixed a possible error when loading workspaces

View File

@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi" LIB_NAME = "dart_ffi"
APPFLOWY_VERSION = "0.4.7" APPFLOWY_VERSION = "0.4.8"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite" FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
PRODUCT_NAME = "AppFlowy" PRODUCT_NAME = "AppFlowy"
MACOSX_DEPLOYMENT_TARGET = "11.0" MACOSX_DEPLOYMENT_TARGET = "11.0"

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.4.7 version: 0.4.8
environment: environment:
flutter: ">=3.18.0-0.2.pre" flutter: ">=3.18.0-0.2.pre"

View File

@ -0,0 +1,50 @@
use crate::util::unzip_history_user_db;
use event_integration::user_event::user_localhost_af_cloud;
use event_integration::EventIntegrationTest;
use flowy_core::DEFAULT_NAME;
use std::time::Duration;
#[tokio::test]
async fn import_appflowy_data_folder_into_new_view_test() {
let import_container_name = "040_local".to_string();
let (cleaner, user_db_path) =
unzip_history_user_db("./tests/asset", &import_container_name).unwrap();
let (imported_af_folder_cleaner, imported_af_data_path) =
unzip_history_user_db("./tests/asset", &import_container_name).unwrap();
user_localhost_af_cloud().await;
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path.clone(), DEFAULT_NAME.to_string())
.await;
// In the 040_local, the structure is:
// workspace:
// view: Document1
// view: Document2
// view: Grid1
// view: Grid2
// Sleep for 2 seconds to wait for the initial workspace to be created
tokio::time::sleep(Duration::from_secs(5)).await;
test
.import_appflowy_data(
imported_af_data_path.to_str().unwrap().to_string(),
Some(import_container_name.clone()),
)
.await
.unwrap();
// after import, the structure is:
// workspace:
// view: Getting Started
// view: 040_local
// view: Document1
// view: Document2
// view: Grid1
// view: Grid2
let views = test.get_all_workspace_views().await;
assert_eq!(views.len(), 2);
assert_eq!(views[1].name, import_container_name);
drop(cleaner);
drop(imported_af_folder_cleaner);
}

View File

@ -1,4 +1,5 @@
mod auth_test; mod auth_test;
mod helper; mod helper;
mod import_af_data_local_test;
mod user_awareness_test; mod user_awareness_test;
mod user_profile_test; mod user_profile_test;

View File

@ -17,7 +17,7 @@ use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use tokio::sync::{Mutex, RwLock}; use tokio::sync::{Mutex, RwLock};
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tracing::{debug, error, event, info, instrument}; use tracing::{debug, error, event, info, instrument, warn};
use lib_dispatch::prelude::af_spawn; use lib_dispatch::prelude::af_spawn;
use lib_infra::box_any::BoxAny; use lib_infra::box_any::BoxAny;
@ -152,8 +152,13 @@ impl UserManager {
user.email user.email
); );
self.prepare_user(&session).await;
self.prepare_backup(&session).await;
// Set the token if the current cloud service using token to authenticate // Set the token if the current cloud service using token to authenticate
// Currently, only the AppFlowy cloud using token to init the client api. // Currently, only the AppFlowy cloud using token to init the client api.
// TODO(nathan): using trait to separate the init process for different cloud service
if user.authenticator.is_appflowy_cloud() {
if let Err(err) = self.cloud_services.set_token(&user.token) { if let Err(err) = self.cloud_services.set_token(&user.token) {
error!("Set token failed: {}", err); error!("Set token failed: {}", err);
} }
@ -183,25 +188,52 @@ impl UserManager {
} }
}, },
UserTokenState::Invalid => { UserTokenState::Invalid => {
// Force user to sign out when the token is invalid // Attempt to upgrade the weak reference for cloud_services
if let (Some(cloud_services), Some(authenticate_user), Some(conn)) = ( let cloud_services = match weak_cloud_services.upgrade() {
weak_cloud_services.upgrade(), Some(cloud_services) => cloud_services,
weak_authenticate_user.upgrade(), None => {
weak_pool.upgrade().and_then(|pool| pool.get().ok()), error!("Failed to upgrade weak reference for cloud_services");
) { return; // Exit early if the upgrade fails
},
};
// Attempt to upgrade the weak reference for authenticate_user
let authenticate_user = match weak_authenticate_user.upgrade() {
Some(authenticate_user) => authenticate_user,
None => {
warn!("Failed to upgrade weak reference for authenticate_user");
return; // Exit early if the upgrade fails
},
};
// Attempt to upgrade the weak reference for pool and then get a connection
let conn = match weak_pool.upgrade() {
Some(pool) => match pool.get() {
Ok(conn) => conn,
Err(_) => {
warn!("Failed to get connection from pool");
return; // Exit early if getting connection fails
},
},
None => {
warn!("Failed to upgrade weak reference for pool");
return; // Exit early if the upgrade fails
},
};
// If all upgrades succeed, proceed with the sign_out operation
if let Err(err) = if let Err(err) =
sign_out(&cloud_services, &cloned_session, &authenticate_user, conn).await sign_out(&cloud_services, &cloned_session, &authenticate_user, conn).await
{ {
error!("Sign out when token invalid failed: {:?}", err); error!("Sign out when token invalid failed: {:?}", err);
} }
} // Force user to sign out when the token is invalid
}, },
} }
} }
}); });
} }
self.prepare_user(&session).await; }
self.prepare_backup(&session).await;
// Do the user data migration if needed // Do the user data migration if needed
event!(tracing::Level::INFO, "Prepare user data migration"); event!(tracing::Level::INFO, "Prepare user data migration");
@ -270,7 +302,7 @@ impl UserManager {
/// ///
/// A sign-in notification is also sent after a successful sign-in. /// A sign-in notification is also sent after a successful sign-in.
/// ///
#[tracing::instrument(level = "debug", skip(self, params))] #[tracing::instrument(level = "info", skip(self, params))]
pub async fn sign_in( pub async fn sign_in(
&self, &self,
params: SignInParams, params: SignInParams,