use std::convert::TryFrom; use std::sync::Weak; use std::{convert::TryInto, sync::Arc}; use flowy_error::{FlowyError, FlowyResult}; use flowy_server_config::supabase_config::SupabaseConfiguration; use flowy_sqlite::kv::StorePreferences; use flowy_user_deps::entities::*; use lib_dispatch::prelude::*; use lib_infra::box_any::BoxAny; use crate::entities::*; use crate::services::{get_supabase_config, UserSession}; fn upgrade_session(session: AFPluginState>) -> FlowyResult> { let session = session .upgrade() .ok_or(FlowyError::internal().context("The user session is already drop"))?; Ok(session) } fn upgrade_store_preferences( store: AFPluginState>, ) -> FlowyResult> { let store = store .upgrade() .ok_or(FlowyError::internal().context("The store preferences is already drop"))?; Ok(store) } #[tracing::instrument(level = "debug", name = "sign_in", skip(data, session), fields(email = %data.email), err)] pub async fn sign_in( data: AFPluginData, session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let params: SignInParams = data.into_inner().try_into()?; let auth_type = params.auth_type.clone(); session.update_auth_type(&auth_type).await; let user_profile: UserProfilePB = session .sign_in(BoxAny::new(params), auth_type) .await? .into(); data_result_ok(user_profile) } #[tracing::instrument( level = "debug", name = "sign_up", skip(data, session), fields( email = %data.email, name = %data.name, ), err )] pub async fn sign_up( data: AFPluginData, session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let params: SignUpParams = data.into_inner().try_into()?; let auth_type = params.auth_type.clone(); session.update_auth_type(&auth_type).await; let user_profile = session.sign_up(auth_type, BoxAny::new(params)).await?; data_result_ok(user_profile.into()) } #[tracing::instrument(level = "debug", skip(session))] pub async fn init_user_handler( session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; session.init_user().await?; Ok(()) } #[tracing::instrument(level = "debug", skip(session))] pub async fn check_user_handler( session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; session.check_user().await?; Ok(()) } #[tracing::instrument(level = "debug", skip(session))] pub async fn get_user_profile_handler( session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let uid = session.get_session()?.user_id; let user_profile: UserProfilePB = session.get_user_profile(uid, true).await?.into(); data_result_ok(user_profile) } #[tracing::instrument(level = "debug", skip(session))] pub async fn sign_out(session: AFPluginState>) -> Result<(), FlowyError> { let session = upgrade_session(session)?; session.sign_out().await?; Ok(()) } #[tracing::instrument(level = "debug", skip(data, session))] pub async fn update_user_profile_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let params: UpdateUserProfileParams = data.into_inner().try_into()?; session.update_user_profile(params).await?; Ok(()) } const APPEARANCE_SETTING_CACHE_KEY: &str = "appearance_settings"; #[tracing::instrument(level = "debug", skip_all, err)] pub async fn set_appearance_setting( store_preferences: AFPluginState>, data: AFPluginData, ) -> Result<(), FlowyError> { let store_preferences = upgrade_store_preferences(store_preferences)?; let mut setting = data.into_inner(); if setting.theme.is_empty() { setting.theme = APPEARANCE_DEFAULT_THEME.to_string(); } store_preferences.set_object(APPEARANCE_SETTING_CACHE_KEY, setting)?; Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] pub async fn get_appearance_setting( store_preferences: AFPluginState>, ) -> DataResult { let store_preferences = upgrade_store_preferences(store_preferences)?; match store_preferences.get_str(APPEARANCE_SETTING_CACHE_KEY) { None => data_result_ok(AppearanceSettingsPB::default()), Some(s) => { let setting = match serde_json::from_str(&s) { Ok(setting) => setting, Err(e) => { tracing::error!( "Deserialize AppearanceSettings failed: {:?}, fallback to default", e ); AppearanceSettingsPB::default() }, }; data_result_ok(setting) }, } } #[tracing::instrument(level = "debug", skip_all, err)] pub async fn get_user_setting( session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let user_setting = session.user_setting()?; data_result_ok(user_setting) } /// Only used for third party auth. /// Use [UserEvent::SignIn] or [UserEvent::SignUp] If the [AuthType] is Local or SelfHosted #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn third_party_auth_handler( data: AFPluginData, session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let params = data.into_inner(); let auth_type: AuthType = params.auth_type.into(); session.update_auth_type(&auth_type).await; let user_profile = session.sign_up(auth_type, BoxAny::new(params.map)).await?; data_result_ok(user_profile.into()) } #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn set_supabase_config_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let config = SupabaseConfiguration::try_from(data.into_inner())?; session.save_supabase_config(config); Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] pub async fn get_supabase_config_handler( store_preferences: AFPluginState>, _session: AFPluginState>, ) -> DataResult { let store_preferences = upgrade_store_preferences(store_preferences)?; let config = get_supabase_config(&store_preferences).unwrap_or_default(); data_result_ok(config.into()) } #[tracing::instrument(level = "debug", skip(session), err)] pub async fn get_all_user_workspace_handler( session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let uid = session.get_session()?.user_id; let user_workspaces = session.get_all_user_workspaces(uid)?; data_result_ok(user_workspaces.into()) } #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn open_workspace_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let params = data.into_inner(); session.open_workspace(¶ms.id).await?; Ok(()) } #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn add_user_to_workspace_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let params = data.into_inner(); session .add_user_to_workspace(params.email, params.workspace_id) .await?; Ok(()) } #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn remove_user_from_workspace_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let params = data.into_inner(); session .remove_user_to_workspace(params.email, params.workspace_id) .await?; Ok(()) } #[tracing::instrument(level = "debug", skip(data, session), err)] pub async fn update_network_state_handler( data: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let session = upgrade_session(session)?; let reachable = data.into_inner().ty.is_reachable(); session .user_status_callback .read() .await .did_update_network(reachable); Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] pub async fn get_historical_users_handler( session: AFPluginState>, ) -> DataResult { let session = upgrade_session(session)?; let users = RepeatedHistoricalUserPB::from(session.get_historical_users()); data_result_ok(users) } #[tracing::instrument(level = "debug", skip_all, err)] pub async fn open_historical_users_handler( user: AFPluginData, session: AFPluginState>, ) -> Result<(), FlowyError> { let user = user.into_inner(); let session = upgrade_session(session)?; session.open_historical_user(user.user_id)?; Ok(()) }