mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: only encrypt if enable (#3236)
* fix: error page display issue * fix: override document with empty data * chore: add logs * fix: encrypt errors * fix: encrypt errors
This commit is contained in:
parent
23a34af30f
commit
de01bf70cd
@ -107,6 +107,9 @@ class SupabaseAuthService implements AuthService {
|
||||
if (!isSupabaseEnabled) {
|
||||
return _appFlowyAuthService.signUpWithOAuth(platform: platform);
|
||||
}
|
||||
// Before signing in, sign out any existing users. Otherwise, the callback will be triggered even if the user doesn't click the 'Sign In' button on the website
|
||||
await _auth.signOut();
|
||||
|
||||
final provider = platform.toProvider();
|
||||
final completer = supabaseLoginCompleter(
|
||||
onSuccess: (userId, userEmail) async {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_svg/flowy_svg.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -71,6 +70,8 @@ class FlowyErrorPage extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const FlowyText.medium(
|
||||
"AppFlowy Error",
|
||||
@ -81,12 +82,14 @@ class FlowyErrorPage extends StatelessWidget {
|
||||
),
|
||||
FlowyText.semibold(
|
||||
message,
|
||||
maxLines: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
height: _titleToMessagePadding,
|
||||
),
|
||||
FlowyText.regular(
|
||||
howToFix,
|
||||
maxLines: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
height: _titleToMessagePadding,
|
||||
|
@ -24,7 +24,7 @@ use flowy_user::event_map::UserCloudServiceProvider;
|
||||
use flowy_user::services::database::{
|
||||
get_user_profile, get_user_workspace, open_collab_db, open_user_db,
|
||||
};
|
||||
use flowy_user_deps::cloud::{UserCloudConfig, UserService};
|
||||
use flowy_user_deps::cloud::UserService;
|
||||
use flowy_user_deps::entities::*;
|
||||
use lib_infra::future::FutureResult;
|
||||
|
||||
@ -75,25 +75,15 @@ impl AppFlowyServerProvider {
|
||||
pub fn new(
|
||||
config: AppFlowyCoreConfig,
|
||||
provider_type: ServerProviderType,
|
||||
cloud_config: Option<UserCloudConfig>,
|
||||
store_preferences: Weak<StorePreferences>,
|
||||
) -> Self {
|
||||
let enable_sync = cloud_config
|
||||
.as_ref()
|
||||
.map(|config| config.enable_sync)
|
||||
.unwrap_or(true);
|
||||
let encryption = EncryptionImpl::new(
|
||||
cloud_config
|
||||
.as_ref()
|
||||
.map(|config| config.encrypt_secret.clone()),
|
||||
);
|
||||
|
||||
let encryption = EncryptionImpl::new(None);
|
||||
Self {
|
||||
config,
|
||||
provider_type: RwLock::new(provider_type),
|
||||
device_id: Default::default(),
|
||||
providers: RwLock::new(HashMap::new()),
|
||||
enable_sync: RwLock::new(enable_sync),
|
||||
enable_sync: RwLock::new(true),
|
||||
encryption: RwLock::new(Arc::new(encryption)),
|
||||
store_preferences,
|
||||
}
|
||||
@ -177,6 +167,7 @@ impl UserCloudServiceProvider for AppFlowyServerProvider {
|
||||
}
|
||||
|
||||
fn set_encrypt_secret(&self, secret: String) {
|
||||
tracing::info!("🔑Set encrypt secret");
|
||||
self.encryption.write().set_secret(secret);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ use flowy_sqlite::kv::StorePreferences;
|
||||
use flowy_task::{TaskDispatcher, TaskRunner};
|
||||
use flowy_user::event_map::{SignUpContext, UserCloudServiceProvider, UserStatusCallback};
|
||||
use flowy_user::manager::{UserManager, UserSessionConfig};
|
||||
use flowy_user::services::cloud_config::get_cloud_config;
|
||||
use flowy_user_deps::cloud::UserCloudConfig;
|
||||
use flowy_user_deps::entities::{AuthType, UserProfile, UserWorkspace};
|
||||
use lib_dispatch::prelude::*;
|
||||
use lib_dispatch::runtime::tokio_default_runtime;
|
||||
@ -150,7 +150,6 @@ impl AppFlowyCore {
|
||||
let server_provider = Arc::new(AppFlowyServerProvider::new(
|
||||
config.clone(),
|
||||
provider_type,
|
||||
get_cloud_config(&store_preference),
|
||||
Arc::downgrade(&store_preference),
|
||||
));
|
||||
|
||||
@ -293,6 +292,7 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||
fn did_init(
|
||||
&self,
|
||||
user_id: i64,
|
||||
cloud_config: &Option<UserCloudConfig>,
|
||||
user_workspace: &UserWorkspace,
|
||||
_device_id: &str,
|
||||
) -> Fut<FlowyResult<()>> {
|
||||
@ -303,6 +303,17 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||
let database_manager = self.database_manager.clone();
|
||||
let document_manager = self.document_manager.clone();
|
||||
|
||||
if let Some(cloud_config) = cloud_config {
|
||||
self
|
||||
.server_provider
|
||||
.set_enable_sync(cloud_config.enable_sync);
|
||||
if cloud_config.enable_encrypt() {
|
||||
self
|
||||
.server_provider
|
||||
.set_encrypt_secret(cloud_config.encrypt_secret.clone());
|
||||
}
|
||||
}
|
||||
|
||||
to_fut(async move {
|
||||
collab_builder.initialize(user_workspace.id.clone());
|
||||
folder_manager
|
||||
|
@ -175,7 +175,7 @@ impl DatabaseManager {
|
||||
let database = wdb
|
||||
.get_database(database_id)
|
||||
.await
|
||||
.ok_or_else(FlowyError::record_not_found)?;
|
||||
.ok_or_else(FlowyError::collab_not_sync)?;
|
||||
|
||||
let editor = Arc::new(DatabaseEditor::new(database, self.task_scheduler.clone()).await?);
|
||||
editors.insert(database_id.to_string(), editor.clone());
|
||||
|
@ -11,7 +11,7 @@ use collab_document::YrsDocAction;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use flowy_document_deps::cloud::DocumentCloudService;
|
||||
use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_error::{internal_error, FlowyError, FlowyResult};
|
||||
|
||||
use crate::document::MutexDocument;
|
||||
use crate::entities::DocumentSnapshotPB;
|
||||
@ -71,6 +71,7 @@ impl DocumentManager {
|
||||
}
|
||||
|
||||
/// Return the document
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn get_document(&self, doc_id: &str) -> FlowyResult<Arc<MutexDocument>> {
|
||||
if let Some(doc) = self.documents.read().get(doc_id) {
|
||||
return Ok(doc.clone());
|
||||
@ -78,16 +79,9 @@ impl DocumentManager {
|
||||
let mut updates = vec![];
|
||||
if !self.is_doc_exist(doc_id)? {
|
||||
// Try to get the document from the cloud service
|
||||
match self.cloud_service.get_document_updates(doc_id).await {
|
||||
Ok(document_updates) => updates = document_updates,
|
||||
Err(e) => {
|
||||
tracing::error!("Get document data failed: {:?}", e);
|
||||
return Err(FlowyError::internal().context("Can't not read the document data"));
|
||||
},
|
||||
}
|
||||
updates = self.cloud_service.get_document_updates(doc_id).await?;
|
||||
}
|
||||
|
||||
tracing::debug!("open_document: {:?}", doc_id);
|
||||
let uid = self.user.user_id()?;
|
||||
let db = self.user.collab_db(uid)?;
|
||||
let collab = self
|
||||
@ -108,17 +102,9 @@ impl DocumentManager {
|
||||
let mut updates = vec![];
|
||||
if !self.is_doc_exist(doc_id)? {
|
||||
if let Ok(document_updates) = self.cloud_service.get_document_updates(doc_id).await {
|
||||
if document_updates.is_empty() {
|
||||
return Err(FlowyError::new(
|
||||
ErrorCode::UnexpectedEmptyCollabUpdates,
|
||||
"Can't not read the document data",
|
||||
));
|
||||
}
|
||||
updates = document_updates;
|
||||
} else {
|
||||
return Err(
|
||||
FlowyError::record_not_found().context(format!("document: {} is not exist", doc_id)),
|
||||
);
|
||||
return Err(FlowyError::collab_not_sync());
|
||||
}
|
||||
}
|
||||
let uid = self.user.user_id()?;
|
||||
|
@ -224,8 +224,8 @@ pub enum ErrorCode {
|
||||
#[error("Invalid decryption secret")]
|
||||
InvalidEncryptSecret = 74,
|
||||
|
||||
#[error("Unexpected empty collab updates")]
|
||||
UnexpectedEmptyCollabUpdates = 75,
|
||||
#[error("It appears that the collaboration object's data has not been fully synchronized")]
|
||||
CollabDataNotSync = 75,
|
||||
}
|
||||
|
||||
impl ErrorCode {
|
||||
|
@ -88,6 +88,7 @@ impl FlowyError {
|
||||
unexpect_calendar_field_type,
|
||||
ErrorCode::UnexpectedCalendarFieldType
|
||||
);
|
||||
static_flowy_error!(collab_not_sync, ErrorCode::CollabDataNotSync);
|
||||
}
|
||||
|
||||
impl std::convert::From<ErrorCode> for FlowyError {
|
||||
|
@ -158,8 +158,8 @@ impl FolderManager {
|
||||
FolderInitializeData::Raw(raw_data) => {
|
||||
if raw_data.is_empty() {
|
||||
return Err(FlowyError::new(
|
||||
ErrorCode::UnexpectedEmptyCollabUpdates,
|
||||
"Can't fetch the workspace data from server",
|
||||
ErrorCode::CollabDataNotSync,
|
||||
"Can't fetch the workspace from server",
|
||||
));
|
||||
}
|
||||
let collab = self.collab_for_folder(uid, &workspace_id, collab_db, raw_data)?;
|
||||
|
@ -38,9 +38,10 @@ where
|
||||
tx.send(
|
||||
async move {
|
||||
let postgrest = try_get_postgrest?;
|
||||
FetchObjectUpdateAction::new(object_id.to_string(), object_ty, postgrest)
|
||||
let updates = FetchObjectUpdateAction::new(object_id.to_string(), object_ty, postgrest)
|
||||
.run_with_fix_interval(5, 10)
|
||||
.await
|
||||
.await?;
|
||||
Ok(updates)
|
||||
}
|
||||
.await,
|
||||
)
|
||||
|
@ -6,6 +6,7 @@ use collab_plugins::cloud_storage::CollabType;
|
||||
use tokio::sync::oneshot::channel;
|
||||
|
||||
use flowy_document_deps::cloud::{DocumentCloudService, DocumentSnapshot};
|
||||
use flowy_error::FlowyError;
|
||||
use lib_infra::future::FutureResult;
|
||||
|
||||
use crate::supabase::api::request::{get_snapshots_from_server, FetchObjectUpdateAction};
|
||||
@ -34,7 +35,11 @@ where
|
||||
async move {
|
||||
let postgrest = try_get_postgrest?;
|
||||
let action = FetchObjectUpdateAction::new(document_id, CollabType::Document, postgrest);
|
||||
action.run_with_fix_interval(5, 10).await
|
||||
let updates = action.run_with_fix_interval(5, 10).await?;
|
||||
if updates.is_empty() {
|
||||
return Err(FlowyError::collab_not_sync().into());
|
||||
}
|
||||
Ok(updates)
|
||||
}
|
||||
.await,
|
||||
)
|
||||
|
@ -65,9 +65,12 @@ impl Action for FetchObjectUpdateAction {
|
||||
Box::pin(async move {
|
||||
match weak_postgres.upgrade() {
|
||||
None => Ok(vec![]),
|
||||
Some(postgrest) => {
|
||||
let items = get_updates_from_server(&object_id, &object_ty, postgrest).await?;
|
||||
Ok(items.into_iter().map(|item| item.value).collect())
|
||||
Some(postgrest) => match get_updates_from_server(&object_id, &object_ty, postgrest).await {
|
||||
Ok(items) => Ok(items.into_iter().map(|item| item.value).collect()),
|
||||
Err(err) => {
|
||||
tracing::error!("Get {} updates failed with error: {:?}", object_id, err);
|
||||
Err(err)
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
@ -112,7 +115,19 @@ impl Action for BatchFetchObjectUpdateAction {
|
||||
Box::pin(async move {
|
||||
match weak_postgrest.upgrade() {
|
||||
None => Ok(CollabObjectUpdateByOid::default()),
|
||||
Some(server) => batch_get_updates_from_server(object_ids, &object_ty, server).await,
|
||||
Some(server) => {
|
||||
match batch_get_updates_from_server(object_ids.clone(), &object_ty, server).await {
|
||||
Ok(updates_by_oid) => Ok(updates_by_oid),
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
"Batch get object with given ids:{:?} failed with error: {:?}",
|
||||
object_ids,
|
||||
err
|
||||
);
|
||||
Err(err)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -349,7 +364,13 @@ fn parser_update_from_json(
|
||||
json.get("value").and_then(|value| value.as_str()),
|
||||
) {
|
||||
(Some(encrypt), Some(value)) => {
|
||||
SupabaseBinaryColumnDecoder::decode(value, encrypt as i32, encryption_secret).ok()
|
||||
match SupabaseBinaryColumnDecoder::decode(value, encrypt as i32, encryption_secret) {
|
||||
Ok(value) => Some(value),
|
||||
Err(err) => {
|
||||
tracing::error!("Decode value column failed: {:?}", err);
|
||||
None
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
@ -371,9 +392,12 @@ fn parser_update_from_json(
|
||||
}
|
||||
Ok(UpdateItem { key, value })
|
||||
} else {
|
||||
let keys = json
|
||||
.as_object()
|
||||
.map(|map| map.iter().map(|(key, _)| key).collect::<Vec<&String>>());
|
||||
Err(anyhow::anyhow!(
|
||||
"missing key or value column in json: {:?}",
|
||||
json
|
||||
"missing key or value column. Current keys:: {:?}",
|
||||
keys
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -152,17 +152,24 @@ impl AppFlowyServer for SupabaseServer {
|
||||
fn handle_realtime_event(&self, json: Value) {
|
||||
match serde_json::from_value::<RealtimeCollabUpdateEvent>(json) {
|
||||
Ok(event) => {
|
||||
if let (Some(tx), Some(secret)) = (
|
||||
self.update_tx.read().get(event.payload.oid.as_str()),
|
||||
self
|
||||
.encryption
|
||||
.upgrade()
|
||||
.and_then(|encryption| encryption.get_secret()),
|
||||
) {
|
||||
if let Some(tx) = self.update_tx.read().get(event.payload.oid.as_str()) {
|
||||
tracing::trace!(
|
||||
"current device: {}, event device: {}",
|
||||
self.did.lock().as_str(),
|
||||
event.payload.did.as_str()
|
||||
);
|
||||
|
||||
if self.did.lock().as_str() != event.payload.did.as_str() {
|
||||
tracing::trace!("Did receive realtime event: {}", event);
|
||||
let value = if event.payload.encrypt == 1 {
|
||||
decrypt_bytes(event.payload.value, &secret).unwrap_or_default()
|
||||
match self
|
||||
.encryption
|
||||
.upgrade()
|
||||
.and_then(|encryption| encryption.get_secret())
|
||||
{
|
||||
None => vec![],
|
||||
Some(secret) => decrypt_bytes(event.payload.value, &secret).unwrap_or_default(),
|
||||
}
|
||||
} else {
|
||||
event.payload.value
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Error;
|
||||
@ -18,7 +19,7 @@ use crate::entities::{
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UserCloudConfig {
|
||||
pub enable_sync: bool,
|
||||
pub enable_encrypt: bool,
|
||||
enable_encrypt: bool,
|
||||
// The secret used to encrypt the user's data
|
||||
pub encrypt_secret: String,
|
||||
}
|
||||
@ -31,6 +32,27 @@ impl UserCloudConfig {
|
||||
encrypt_secret,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_encrypt(&self) -> bool {
|
||||
self.enable_encrypt
|
||||
}
|
||||
|
||||
pub fn with_enable_encrypt(mut self, enable_encrypt: bool) -> Self {
|
||||
self.enable_encrypt = enable_encrypt;
|
||||
// When the enable_encrypt is true, the encrypt_secret should not be empty
|
||||
debug_assert!(!self.encrypt_secret.is_empty());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UserCloudConfig {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"enable_sync: {}, enable_encrypt: {}",
|
||||
self.enable_sync, self.enable_encrypt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide the generic interface for the user cloud service
|
||||
|
@ -149,7 +149,7 @@ impl From<UserCloudConfig> for UserCloudConfigPB {
|
||||
fn from(value: UserCloudConfig) -> Self {
|
||||
Self {
|
||||
enable_sync: value.enable_sync,
|
||||
enable_encrypt: value.enable_encrypt,
|
||||
enable_encrypt: value.enable_encrypt(),
|
||||
encrypt_secret: value.encrypt_secret,
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use serde_json::Value;
|
||||
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sqlite::kv::StorePreferences;
|
||||
use flowy_user_deps::cloud::UserCloudConfig;
|
||||
use flowy_user_deps::entities::*;
|
||||
use lib_dispatch::prelude::*;
|
||||
use lib_infra::box_any::BoxAny;
|
||||
@ -12,7 +13,9 @@ use lib_infra::box_any::BoxAny;
|
||||
use crate::entities::*;
|
||||
use crate::manager::UserManager;
|
||||
use crate::notification::{send_notification, UserNotification};
|
||||
use crate::services::cloud_config::{generate_cloud_config, get_cloud_config, save_cloud_config};
|
||||
use crate::services::cloud_config::{
|
||||
get_cloud_config, get_or_create_cloud_config, save_cloud_config,
|
||||
};
|
||||
|
||||
fn upgrade_manager(manager: AFPluginState<Weak<UserManager>>) -> FlowyResult<Arc<UserManager>> {
|
||||
let manager = manager
|
||||
@ -186,12 +189,6 @@ pub async fn set_encrypt_secret_handler(
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let store_preferences = upgrade_store_preferences(store_preferences)?;
|
||||
let data = data.into_inner();
|
||||
|
||||
let mut config = get_cloud_config(&store_preferences).unwrap_or_else(|| {
|
||||
tracing::trace!("Generate default cloud config");
|
||||
generate_cloud_config(&store_preferences)
|
||||
});
|
||||
|
||||
match data.encryption_type {
|
||||
EncryptionTypePB::NoEncryption => {
|
||||
tracing::error!("Encryption type is NoEncryption, but set encrypt secret");
|
||||
@ -203,8 +200,7 @@ pub async fn set_encrypt_secret_handler(
|
||||
&data.encryption_secret,
|
||||
)?;
|
||||
|
||||
config.encrypt_secret = data.encryption_secret;
|
||||
config.enable_encrypt = true;
|
||||
let config = UserCloudConfig::new(data.encryption_secret).with_enable_encrypt(true);
|
||||
manager
|
||||
.set_encrypt_secret(
|
||||
data.user_id,
|
||||
@ -212,10 +208,10 @@ pub async fn set_encrypt_secret_handler(
|
||||
EncryptionType::SelfEncryption(data.encryption_sign),
|
||||
)
|
||||
.await?;
|
||||
save_cloud_config(data.user_id, &store_preferences, config)?;
|
||||
},
|
||||
}
|
||||
|
||||
save_cloud_config(data.user_id, &store_preferences, config)?;
|
||||
manager.resume_sign_up().await?;
|
||||
Ok(())
|
||||
}
|
||||
@ -250,9 +246,9 @@ pub async fn set_cloud_config_handler(
|
||||
) -> Result<(), FlowyError> {
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let session = manager.get_session()?;
|
||||
let store_preferences = upgrade_store_preferences(store_preferences)?;
|
||||
let update = data.into_inner();
|
||||
let mut config = get_cloud_config(&store_preferences)
|
||||
let store_preferences = upgrade_store_preferences(store_preferences)?;
|
||||
let mut config = get_cloud_config(session.user_id, &store_preferences)
|
||||
.ok_or(FlowyError::internal().context("Can't find any cloud config"))?;
|
||||
|
||||
if let Some(enable_sync) = update.enable_sync {
|
||||
@ -261,20 +257,21 @@ pub async fn set_cloud_config_handler(
|
||||
}
|
||||
|
||||
if let Some(enable_encrypt) = update.enable_encrypt {
|
||||
config.enable_encrypt = enable_encrypt;
|
||||
debug_assert!(enable_encrypt, "Disable encryption is not supported");
|
||||
|
||||
if enable_encrypt {
|
||||
tracing::info!("Enable encryption for user: {}", session.user_id);
|
||||
config = config.with_enable_encrypt(enable_encrypt);
|
||||
let encrypt_secret = config.encrypt_secret.clone();
|
||||
|
||||
// The encryption secret is generated when the user first enables encryption and will be
|
||||
// used to validate the encryption secret is correct when the user logs in.
|
||||
let encryption_sign =
|
||||
manager.generate_encryption_sign(session.user_id, &config.encrypt_secret)?;
|
||||
let encryption_sign = manager.generate_encryption_sign(session.user_id, &encrypt_secret)?;
|
||||
let encryption_type = EncryptionType::SelfEncryption(encryption_sign);
|
||||
manager
|
||||
.set_encrypt_secret(
|
||||
session.user_id,
|
||||
config.encrypt_secret.clone(),
|
||||
encryption_type.clone(),
|
||||
)
|
||||
.set_encrypt_secret(session.user_id, encrypt_secret, encryption_type.clone())
|
||||
.await?;
|
||||
save_cloud_config(session.user_id, &store_preferences, config.clone())?;
|
||||
|
||||
let params =
|
||||
UpdateUserProfileParams::new(session.user_id).with_encryption_type(encryption_type);
|
||||
@ -282,8 +279,7 @@ pub async fn set_cloud_config_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let config_pb = UserCloudConfigPB::from(config.clone());
|
||||
save_cloud_config(session.user_id, &store_preferences, config)?;
|
||||
let config_pb = UserCloudConfigPB::from(config);
|
||||
send_notification(
|
||||
&session.user_id.to_string(),
|
||||
UserNotification::DidUpdateCloudConfig,
|
||||
@ -295,12 +291,15 @@ pub async fn set_cloud_config_handler(
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub async fn get_cloud_config_handler(
|
||||
manager: AFPluginState<Weak<UserManager>>,
|
||||
store_preferences: AFPluginState<Weak<StorePreferences>>,
|
||||
) -> DataResult<UserCloudConfigPB, FlowyError> {
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let session = manager.get_session()?;
|
||||
|
||||
let store_preferences = upgrade_store_preferences(store_preferences)?;
|
||||
// Generate the default config if the config is not exist
|
||||
let config = get_cloud_config(&store_preferences)
|
||||
.unwrap_or_else(|| generate_cloud_config(&store_preferences));
|
||||
let config = get_or_create_cloud_config(session.user_id, &store_preferences);
|
||||
data_result_ok(config.into())
|
||||
}
|
||||
|
||||
@ -389,7 +388,6 @@ pub async fn open_historical_users_handler(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub async fn push_realtime_event_handler(
|
||||
payload: AFPluginData<RealtimePayloadPB>,
|
||||
manager: AFPluginState<Weak<UserManager>>,
|
||||
|
@ -6,7 +6,7 @@ use strum_macros::Display;
|
||||
|
||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_user_deps::cloud::UserService;
|
||||
use flowy_user_deps::cloud::{UserCloudConfig, UserService};
|
||||
use flowy_user_deps::entities::*;
|
||||
use lib_dispatch::prelude::*;
|
||||
use lib_infra::future::{to_fut, Fut};
|
||||
@ -74,6 +74,7 @@ pub trait UserStatusCallback: Send + Sync + 'static {
|
||||
fn did_init(
|
||||
&self,
|
||||
user_id: i64,
|
||||
cloud_config: &Option<UserCloudConfig>,
|
||||
user_workspace: &UserWorkspace,
|
||||
device_id: &str,
|
||||
) -> Fut<FlowyResult<()>>;
|
||||
@ -145,6 +146,7 @@ impl UserStatusCallback for DefaultUserStatusCallback {
|
||||
fn did_init(
|
||||
&self,
|
||||
_user_id: i64,
|
||||
_cloud_config: &Option<UserCloudConfig>,
|
||||
_user_workspace: &UserWorkspace,
|
||||
_device_id: &str,
|
||||
) -> Fut<FlowyResult<()>> {
|
||||
|
@ -25,7 +25,7 @@ use crate::migrations::historical_document::HistoricalEmptyDocumentMigration;
|
||||
use crate::migrations::local_user_to_cloud::migration_user_to_cloud;
|
||||
use crate::migrations::migration::UserLocalDataMigration;
|
||||
use crate::migrations::MigrationUser;
|
||||
use crate::services::cloud_config::remove_cloud_config;
|
||||
use crate::services::cloud_config::get_cloud_config;
|
||||
use crate::services::database::UserDB;
|
||||
use crate::services::entities::{ResumableSignUp, Session};
|
||||
use crate::services::user_awareness::UserAwarenessDataSource;
|
||||
@ -121,8 +121,14 @@ impl UserManager {
|
||||
self
|
||||
.initialize_user_awareness(&session, UserAwarenessDataSource::Local)
|
||||
.await;
|
||||
let cloud_config = get_cloud_config(session.user_id, &self.store_preferences);
|
||||
if let Err(e) = user_status_callback
|
||||
.did_init(session.user_id, &session.user_workspace, &session.device_id)
|
||||
.did_init(
|
||||
session.user_id,
|
||||
&cloud_config,
|
||||
&session.user_workspace,
|
||||
&session.device_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::error!("Failed to call did_init callback: {:?}", e);
|
||||
@ -213,7 +219,6 @@ impl UserManager {
|
||||
auth_type: AuthType,
|
||||
params: BoxAny,
|
||||
) -> Result<UserProfile, FlowyError> {
|
||||
remove_cloud_config(&self.store_preferences);
|
||||
self.update_auth_type(&auth_type).await;
|
||||
|
||||
let migration_user = self.get_migration_user(&auth_type).await;
|
||||
@ -325,7 +330,6 @@ impl UserManager {
|
||||
let session = self.get_session()?;
|
||||
self.database.close(session.user_id)?;
|
||||
self.set_current_session(None)?;
|
||||
remove_cloud_config(&self.store_preferences);
|
||||
|
||||
let server = self.cloud_services.get_user_service()?;
|
||||
tokio::spawn(async move {
|
||||
|
@ -7,41 +7,48 @@ use flowy_user_deps::cloud::UserCloudConfig;
|
||||
|
||||
const CLOUD_CONFIG_KEY: &str = "af_user_cloud_config";
|
||||
|
||||
pub fn generate_cloud_config(store_preference: &Arc<StorePreferences>) -> UserCloudConfig {
|
||||
fn generate_cloud_config(uid: i64, store_preference: &Arc<StorePreferences>) -> UserCloudConfig {
|
||||
let config = UserCloudConfig::new(generate_encrypt_secret());
|
||||
let key = cache_key_for_cloud_config();
|
||||
let key = cache_key_for_cloud_config(uid);
|
||||
store_preference.set_object(&key, config.clone()).unwrap();
|
||||
config
|
||||
}
|
||||
|
||||
pub fn remove_cloud_config(store_preference: &Arc<StorePreferences>) {
|
||||
let key = cache_key_for_cloud_config();
|
||||
store_preference.remove(&key);
|
||||
}
|
||||
|
||||
pub fn save_cloud_config(
|
||||
uid: i64,
|
||||
store_preference: &Arc<StorePreferences>,
|
||||
config: UserCloudConfig,
|
||||
) -> FlowyResult<()> {
|
||||
let encrypt_secret = config.encrypt_secret.clone();
|
||||
let key = cache_key_for_cloud_config();
|
||||
tracing::info!("save user:{} cloud config: {}", uid, config);
|
||||
let key = cache_key_for_cloud_config(uid);
|
||||
store_preference.set_object(&key, config)?;
|
||||
store_preference.set_object(&format!("{}-encrypt-secret", uid), encrypt_secret)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cache_key_for_cloud_config() -> String {
|
||||
CLOUD_CONFIG_KEY.to_string()
|
||||
fn cache_key_for_cloud_config(uid: i64) -> String {
|
||||
format!("{}:{}", CLOUD_CONFIG_KEY, uid)
|
||||
}
|
||||
|
||||
pub fn get_cloud_config(store_preference: &Arc<StorePreferences>) -> Option<UserCloudConfig> {
|
||||
let key = cache_key_for_cloud_config();
|
||||
pub fn get_cloud_config(
|
||||
uid: i64,
|
||||
store_preference: &Arc<StorePreferences>,
|
||||
) -> Option<UserCloudConfig> {
|
||||
let key = cache_key_for_cloud_config(uid);
|
||||
store_preference.get_object::<UserCloudConfig>(&key)
|
||||
}
|
||||
|
||||
pub fn get_encrypt_secret(store_preference: &Arc<StorePreferences>) -> Option<String> {
|
||||
let key = cache_key_for_cloud_config();
|
||||
pub fn get_or_create_cloud_config(
|
||||
uid: i64,
|
||||
store_preferences: &Arc<StorePreferences>,
|
||||
) -> UserCloudConfig {
|
||||
let key = cache_key_for_cloud_config(uid);
|
||||
store_preferences
|
||||
.get_object::<UserCloudConfig>(&key)
|
||||
.unwrap_or_else(|| generate_cloud_config(uid, store_preferences))
|
||||
}
|
||||
|
||||
pub fn get_encrypt_secret(uid: i64, store_preference: &Arc<StorePreferences>) -> Option<String> {
|
||||
let key = cache_key_for_cloud_config(uid);
|
||||
store_preference
|
||||
.get_object::<UserCloudConfig>(&key)
|
||||
.map(|config| config.encrypt_secret)
|
||||
|
@ -37,7 +37,7 @@ impl UserManager {
|
||||
"Failed to get store preference",
|
||||
))?;
|
||||
|
||||
let encrypt_secret = get_encrypt_secret(&store_preference).ok_or(FlowyError::new(
|
||||
let encrypt_secret = get_encrypt_secret(uid, &store_preference).ok_or(FlowyError::new(
|
||||
ErrorCode::Internal,
|
||||
"Encrypt secret is not set",
|
||||
))?;
|
||||
|
Loading…
Reference in New Issue
Block a user