Skip to content

Commit e81a2ff

Browse files
authored
fix: token refresh on local (#4650)
* fix: refresh user token on local * chore: add test
1 parent b356927 commit e81a2ff

File tree

6 files changed

+126
-43
lines changed

6 files changed

+126
-43
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Release Notes
2-
## Version 0.4.7 - 02/08/2024
2+
## Version 0.4.8 - 02/13/2024
33
### Bug Fixes
44
- Fixed a possible error when loading workspaces
55

frontend/Makefile.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
2626
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
2727
CARGO_MAKE_CRATE_NAME = "dart-ffi"
2828
LIB_NAME = "dart_ffi"
29-
APPFLOWY_VERSION = "0.4.7"
29+
APPFLOWY_VERSION = "0.4.8"
3030
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
3131
PRODUCT_NAME = "AppFlowy"
3232
MACOSX_DEPLOYMENT_TARGET = "11.0"

frontend/appflowy_flutter/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
1515
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
1616
# Read more about iOS versioning at
1717
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18-
version: 0.4.7
18+
version: 0.4.8
1919

2020
environment:
2121
flutter: ">=3.18.0-0.2.pre"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::util::unzip_history_user_db;
2+
use event_integration::user_event::user_localhost_af_cloud;
3+
use event_integration::EventIntegrationTest;
4+
use flowy_core::DEFAULT_NAME;
5+
use std::time::Duration;
6+
7+
#[tokio::test]
8+
async fn import_appflowy_data_folder_into_new_view_test() {
9+
let import_container_name = "040_local".to_string();
10+
let (cleaner, user_db_path) =
11+
unzip_history_user_db("./tests/asset", &import_container_name).unwrap();
12+
let (imported_af_folder_cleaner, imported_af_data_path) =
13+
unzip_history_user_db("./tests/asset", &import_container_name).unwrap();
14+
15+
user_localhost_af_cloud().await;
16+
let test =
17+
EventIntegrationTest::new_with_user_data_path(user_db_path.clone(), DEFAULT_NAME.to_string())
18+
.await;
19+
// In the 040_local, the structure is:
20+
// workspace:
21+
// view: Document1
22+
// view: Document2
23+
// view: Grid1
24+
// view: Grid2
25+
// Sleep for 2 seconds to wait for the initial workspace to be created
26+
tokio::time::sleep(Duration::from_secs(5)).await;
27+
28+
test
29+
.import_appflowy_data(
30+
imported_af_data_path.to_str().unwrap().to_string(),
31+
Some(import_container_name.clone()),
32+
)
33+
.await
34+
.unwrap();
35+
36+
// after import, the structure is:
37+
// workspace:
38+
// view: Getting Started
39+
// view: 040_local
40+
// view: Document1
41+
// view: Document2
42+
// view: Grid1
43+
// view: Grid2
44+
let views = test.get_all_workspace_views().await;
45+
assert_eq!(views.len(), 2);
46+
assert_eq!(views[1].name, import_container_name);
47+
48+
drop(cleaner);
49+
drop(imported_af_folder_cleaner);
50+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod auth_test;
22
mod helper;
3+
mod import_af_data_local_test;
34
mod user_awareness_test;
45
mod user_profile_test;

frontend/rust-lib/flowy-user/src/user_manager/manager.rs

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::sync::atomic::{AtomicI64, Ordering};
1717
use std::sync::{Arc, Weak};
1818
use tokio::sync::{Mutex, RwLock};
1919
use tokio_stream::StreamExt;
20-
use tracing::{debug, error, event, info, instrument};
20+
use tracing::{debug, error, event, info, instrument, warn};
2121

2222
use lib_dispatch::prelude::af_spawn;
2323
use lib_infra::box_any::BoxAny;
@@ -152,56 +152,88 @@ impl UserManager {
152152
user.email
153153
);
154154

155+
self.prepare_user(&session).await;
156+
self.prepare_backup(&session).await;
157+
155158
// Set the token if the current cloud service using token to authenticate
156159
// Currently, only the AppFlowy cloud using token to init the client api.
157-
if let Err(err) = self.cloud_services.set_token(&user.token) {
158-
error!("Set token failed: {}", err);
159-
}
160+
// TODO(nathan): using trait to separate the init process for different cloud service
161+
if user.authenticator.is_appflowy_cloud() {
162+
if let Err(err) = self.cloud_services.set_token(&user.token) {
163+
error!("Set token failed: {}", err);
164+
}
160165

161-
// Subscribe the token state
162-
let weak_cloud_services = Arc::downgrade(&self.cloud_services);
163-
let weak_authenticate_user = Arc::downgrade(&self.authenticate_user);
164-
let weak_pool = Arc::downgrade(&self.db_pool(user.uid)?);
165-
let cloned_session = session.clone();
166-
if let Some(mut token_state_rx) = self.cloud_services.subscribe_token_state() {
167-
event!(tracing::Level::DEBUG, "Listen token state change");
168-
let user_uid = user.uid;
169-
let local_token = user.token.clone();
170-
af_spawn(async move {
171-
while let Some(token_state) = token_state_rx.next().await {
172-
debug!("Token state changed: {:?}", token_state);
173-
match token_state {
174-
UserTokenState::Refresh { token: new_token } => {
175-
// Only save the token if the token is different from the current token
176-
if new_token != local_token {
177-
if let Some(conn) = weak_pool.upgrade().and_then(|pool| pool.get().ok()) {
178-
// Save the new token
179-
if let Err(err) = save_user_token(user_uid, conn, new_token) {
180-
error!("Save user token failed: {}", err);
166+
// Subscribe the token state
167+
let weak_cloud_services = Arc::downgrade(&self.cloud_services);
168+
let weak_authenticate_user = Arc::downgrade(&self.authenticate_user);
169+
let weak_pool = Arc::downgrade(&self.db_pool(user.uid)?);
170+
let cloned_session = session.clone();
171+
if let Some(mut token_state_rx) = self.cloud_services.subscribe_token_state() {
172+
event!(tracing::Level::DEBUG, "Listen token state change");
173+
let user_uid = user.uid;
174+
let local_token = user.token.clone();
175+
af_spawn(async move {
176+
while let Some(token_state) = token_state_rx.next().await {
177+
debug!("Token state changed: {:?}", token_state);
178+
match token_state {
179+
UserTokenState::Refresh { token: new_token } => {
180+
// Only save the token if the token is different from the current token
181+
if new_token != local_token {
182+
if let Some(conn) = weak_pool.upgrade().and_then(|pool| pool.get().ok()) {
183+
// Save the new token
184+
if let Err(err) = save_user_token(user_uid, conn, new_token) {
185+
error!("Save user token failed: {}", err);
186+
}
181187
}
182188
}
183-
}
184-
},
185-
UserTokenState::Invalid => {
186-
// Force user to sign out when the token is invalid
187-
if let (Some(cloud_services), Some(authenticate_user), Some(conn)) = (
188-
weak_cloud_services.upgrade(),
189-
weak_authenticate_user.upgrade(),
190-
weak_pool.upgrade().and_then(|pool| pool.get().ok()),
191-
) {
189+
},
190+
UserTokenState::Invalid => {
191+
// Attempt to upgrade the weak reference for cloud_services
192+
let cloud_services = match weak_cloud_services.upgrade() {
193+
Some(cloud_services) => cloud_services,
194+
None => {
195+
error!("Failed to upgrade weak reference for cloud_services");
196+
return; // Exit early if the upgrade fails
197+
},
198+
};
199+
200+
// Attempt to upgrade the weak reference for authenticate_user
201+
let authenticate_user = match weak_authenticate_user.upgrade() {
202+
Some(authenticate_user) => authenticate_user,
203+
None => {
204+
warn!("Failed to upgrade weak reference for authenticate_user");
205+
return; // Exit early if the upgrade fails
206+
},
207+
};
208+
209+
// Attempt to upgrade the weak reference for pool and then get a connection
210+
let conn = match weak_pool.upgrade() {
211+
Some(pool) => match pool.get() {
212+
Ok(conn) => conn,
213+
Err(_) => {
214+
warn!("Failed to get connection from pool");
215+
return; // Exit early if getting connection fails
216+
},
217+
},
218+
None => {
219+
warn!("Failed to upgrade weak reference for pool");
220+
return; // Exit early if the upgrade fails
221+
},
222+
};
223+
224+
// If all upgrades succeed, proceed with the sign_out operation
192225
if let Err(err) =
193226
sign_out(&cloud_services, &cloned_session, &authenticate_user, conn).await
194227
{
195228
error!("Sign out when token invalid failed: {:?}", err);
196229
}
197-
}
198-
},
230+
// Force user to sign out when the token is invalid
231+
},
232+
}
199233
}
200-
}
201-
});
234+
});
235+
}
202236
}
203-
self.prepare_user(&session).await;
204-
self.prepare_backup(&session).await;
205237

206238
// Do the user data migration if needed
207239
event!(tracing::Level::INFO, "Prepare user data migration");
@@ -270,7 +302,7 @@ impl UserManager {
270302
///
271303
/// A sign-in notification is also sent after a successful sign-in.
272304
///
273-
#[tracing::instrument(level = "debug", skip(self, params))]
305+
#[tracing::instrument(level = "info", skip(self, params))]
274306
pub async fn sign_in(
275307
&self,
276308
params: SignInParams,

0 commit comments

Comments
 (0)