mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: folder with yrs
* feat: try using folder2 * feat: update * feat: implement handlers * fix: compile errors * chore: add unsafe send + sync * feat: remove unsafe impl * fix: replace folder with foler2 * chore: dart compile errors * test: fix test * test: fix test * test: bypass existing tests * feat: open latest view * chore: fix dart warnings * chore: config notification * fix: folder notification bugs * fix: doesn't open the new view after creating * chore: rename struct * refactor: user id * test: fix test * chore: remove unused user_id * fix: fix read workspace views * chore: rename appflowy data folder * chore: update ref * fix: tauri build
This commit is contained in:
@ -13,6 +13,8 @@ user-model = { path = "../../../shared-lib/user-model" }
|
||||
lib-infra = { path = "../../../shared-lib/lib-infra" }
|
||||
flowy-notification = { path = "../flowy-notification" }
|
||||
lib-dispatch = { path = "../lib-dispatch" }
|
||||
collab-persistence = { version = "0.1.0" }
|
||||
|
||||
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
bytes = "1.4"
|
||||
|
@ -2,8 +2,7 @@ use crate::errors::ErrorCode;
|
||||
use flowy_derive::ProtoBuf;
|
||||
use std::convert::TryInto;
|
||||
use user_model::{
|
||||
UpdateUserProfileParams, UserEmail, UserIcon, UserId, UserName, UserOpenaiKey, UserPassword,
|
||||
UserProfile,
|
||||
UpdateUserProfileParams, UserEmail, UserIcon, UserName, UserOpenaiKey, UserPassword, UserProfile,
|
||||
};
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
@ -21,7 +20,7 @@ pub struct UserSettingPB {
|
||||
#[derive(ProtoBuf, Default, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct UserProfilePB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
pub id: i64,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub email: String,
|
||||
@ -55,7 +54,7 @@ impl std::convert::From<UserProfile> for UserProfilePB {
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct UpdateUserProfilePayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
pub id: i64,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub name: Option<String>,
|
||||
@ -74,9 +73,9 @@ pub struct UpdateUserProfilePayloadPB {
|
||||
}
|
||||
|
||||
impl UpdateUserProfilePayloadPB {
|
||||
pub fn new(id: &str) -> Self {
|
||||
pub fn new(id: i64) -> Self {
|
||||
Self {
|
||||
id: id.to_owned(),
|
||||
id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@ -111,8 +110,6 @@ impl TryInto<UpdateUserProfileParams> for UpdateUserProfilePayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<UpdateUserProfileParams, Self::Error> {
|
||||
let id = UserId::parse(self.id)?.0;
|
||||
|
||||
let name = match self.name {
|
||||
None => None,
|
||||
Some(name) => Some(UserName::parse(name)?.0),
|
||||
@ -139,7 +136,7 @@ impl TryInto<UpdateUserProfileParams> for UpdateUserProfilePayloadPB {
|
||||
};
|
||||
|
||||
Ok(UpdateUserProfileParams {
|
||||
id,
|
||||
id: self.id,
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
|
@ -1,12 +1,41 @@
|
||||
use crate::entities::{
|
||||
AppearanceSettingsPB, UpdateUserProfilePayloadPB, UserProfilePB, UserSettingPB,
|
||||
APPEARANCE_DEFAULT_THEME,
|
||||
};
|
||||
use crate::{errors::FlowyError, services::UserSession};
|
||||
use crate::entities::*;
|
||||
use crate::services::UserSession;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_sqlite::kv::KV;
|
||||
use lib_dispatch::prelude::*;
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
use user_model::UpdateUserProfileParams;
|
||||
use user_model::{SignInParams, SignUpParams, UpdateUserProfileParams};
|
||||
|
||||
// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
|
||||
#[tracing::instrument(level = "debug", name = "sign_in", skip(data, session), fields(email = %data.email), err)]
|
||||
pub async fn sign_in(
|
||||
data: AFPluginData<SignInPayloadPB>,
|
||||
session: AFPluginState<Arc<UserSession>>,
|
||||
) -> DataResult<UserProfilePB, FlowyError> {
|
||||
let params: SignInParams = data.into_inner().try_into()?;
|
||||
let user_profile: UserProfilePB = session.sign_in(params).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<SignUpPayloadPB>,
|
||||
session: AFPluginState<Arc<UserSession>>,
|
||||
) -> DataResult<UserProfilePB, FlowyError> {
|
||||
let params: SignUpParams = data.into_inner().try_into()?;
|
||||
let user_profile: UserProfilePB = session.sign_up(params).await?.into();
|
||||
|
||||
data_result_ok(user_profile)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(session))]
|
||||
pub async fn init_user_handler(session: AFPluginState<Arc<UserSession>>) -> Result<(), FlowyError> {
|
@ -1,9 +1,12 @@
|
||||
use crate::entities::UserProfilePB;
|
||||
use crate::{errors::FlowyError, handlers::*, services::UserSession};
|
||||
use crate::event_handler::*;
|
||||
use crate::{errors::FlowyError, services::UserSession};
|
||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||
use flowy_error::FlowyResult;
|
||||
use lib_dispatch::prelude::*;
|
||||
|
||||
use lib_infra::future::{Fut, FutureResult};
|
||||
use std::sync::Arc;
|
||||
use strum_macros::Display;
|
||||
use user_model::{
|
||||
SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
|
||||
};
|
||||
@ -25,9 +28,10 @@ pub fn init(user_session: Arc<UserSession>) -> AFPlugin {
|
||||
}
|
||||
|
||||
pub trait UserStatusCallback: Send + Sync + 'static {
|
||||
fn did_sign_in(&self, token: &str, user_id: &str) -> Fut<FlowyResult<()>>;
|
||||
fn did_sign_in(&self, token: &str, user_id: i64) -> Fut<FlowyResult<()>>;
|
||||
fn did_sign_up(&self, user_profile: &UserProfile) -> Fut<FlowyResult<()>>;
|
||||
fn did_expired(&self, token: &str, user_id: &str) -> Fut<FlowyResult<()>>;
|
||||
fn did_expired(&self, token: &str, user_id: i64) -> Fut<FlowyResult<()>>;
|
||||
fn will_migrated(&self, token: &str, old_user_id: &str, user_id: i64) -> Fut<FlowyResult<()>>;
|
||||
}
|
||||
|
||||
pub trait UserCloudService: Send + Sync {
|
||||
@ -43,10 +47,6 @@ pub trait UserCloudService: Send + Sync {
|
||||
fn ws_addr(&self) -> String;
|
||||
}
|
||||
|
||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||
use flowy_error::FlowyResult;
|
||||
use strum_macros::Display;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||
#[event_err = "FlowyError"]
|
||||
pub enum UserEvent {
|
||||
|
@ -1,37 +0,0 @@
|
||||
use crate::entities::*;
|
||||
use crate::services::UserSession;
|
||||
use flowy_error::FlowyError;
|
||||
use lib_dispatch::prelude::*;
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
use user_model::{SignInParams, SignUpParams};
|
||||
|
||||
// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
|
||||
#[tracing::instrument(level = "debug", name = "sign_in", skip(data, session), fields(email = %data.email), err)]
|
||||
pub async fn sign_in(
|
||||
data: AFPluginData<SignInPayloadPB>,
|
||||
session: AFPluginState<Arc<UserSession>>,
|
||||
) -> DataResult<UserProfilePB, FlowyError> {
|
||||
let params: SignInParams = data.into_inner().try_into()?;
|
||||
let user_profile: UserProfilePB = session.sign_in(params).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<SignUpPayloadPB>,
|
||||
session: AFPluginState<Arc<UserSession>>,
|
||||
) -> DataResult<UserProfilePB, FlowyError> {
|
||||
let params: SignUpParams = data.into_inner().try_into()?;
|
||||
let user_profile: UserProfilePB = session.sign_up(params).await?.into();
|
||||
|
||||
data_result_ok(user_profile)
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
mod auth_handler;
|
||||
mod user_handler;
|
||||
|
||||
pub use auth_handler::*;
|
||||
pub use user_handler::*;
|
@ -1,9 +1,10 @@
|
||||
pub mod entities;
|
||||
mod event_handler;
|
||||
pub mod event_map;
|
||||
mod handlers;
|
||||
mod notification;
|
||||
pub mod protobuf;
|
||||
pub mod services;
|
||||
pub mod uid;
|
||||
// mod sql_tables;
|
||||
|
||||
#[macro_use]
|
||||
|
@ -1,4 +1,5 @@
|
||||
use flowy_error::{ErrorCode, FlowyError};
|
||||
use collab_persistence::CollabKV;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_sqlite::ConnectionPool;
|
||||
use flowy_sqlite::{schema::user_table, DBConnection, Database};
|
||||
use lazy_static::lazy_static;
|
||||
@ -18,25 +19,21 @@ impl UserDB {
|
||||
}
|
||||
}
|
||||
|
||||
fn open_user_db_if_need(&self, user_id: &str) -> Result<Arc<ConnectionPool>, FlowyError> {
|
||||
if user_id.is_empty() {
|
||||
return Err(ErrorCode::UserIdIsEmpty.into());
|
||||
}
|
||||
|
||||
if let Some(database) = DB_MAP.read().get(user_id) {
|
||||
fn open_user_db_if_need(&self, user_id: i64) -> Result<Arc<ConnectionPool>, FlowyError> {
|
||||
if let Some(database) = DB_MAP.read().get(&user_id) {
|
||||
return Ok(database.get_pool());
|
||||
}
|
||||
|
||||
let mut write_guard = DB_MAP.write();
|
||||
// The Write guard acquire exclusive access that will guarantee the user db only initialize once.
|
||||
match write_guard.get(user_id) {
|
||||
match write_guard.get(&user_id) {
|
||||
None => {},
|
||||
Some(database) => return Ok(database.get_pool()),
|
||||
}
|
||||
|
||||
let mut dir = PathBuf::new();
|
||||
dir.push(&self.db_dir);
|
||||
dir.push(user_id);
|
||||
dir.push(user_id.to_string());
|
||||
let dir = dir.to_str().unwrap().to_owned();
|
||||
|
||||
tracing::trace!("open user db {} at path: {}", user_id, dir);
|
||||
@ -50,29 +47,59 @@ impl UserDB {
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), FlowyError> {
|
||||
fn open_kv_db_if_need(&self, user_id: i64) -> Result<Arc<CollabKV>, FlowyError> {
|
||||
if let Some(kv) = KVDB_MAP.read().get(&user_id) {
|
||||
return Ok(kv.clone());
|
||||
}
|
||||
|
||||
let mut write_guard = KVDB_MAP.write();
|
||||
// The Write guard acquire exclusive access that will guarantee the user db only initialize once.
|
||||
match write_guard.get(&user_id) {
|
||||
None => {},
|
||||
Some(kv) => return Ok(kv.clone()),
|
||||
}
|
||||
|
||||
let mut dir = PathBuf::new();
|
||||
dir.push(&self.db_dir);
|
||||
dir.push(user_id.to_string());
|
||||
|
||||
tracing::trace!("open kv db {} at path: {:?}", user_id, dir);
|
||||
let kv_db = CollabKV::open(dir).map_err(|err| FlowyError::internal().context(err))?;
|
||||
let kv_db = Arc::new(kv_db);
|
||||
write_guard.insert(user_id.to_owned(), kv_db.clone());
|
||||
drop(write_guard);
|
||||
Ok(kv_db)
|
||||
}
|
||||
|
||||
pub(crate) fn close_user_db(&self, user_id: i64) -> Result<(), FlowyError> {
|
||||
match DB_MAP.try_write_for(Duration::from_millis(300)) {
|
||||
None => Err(FlowyError::internal().context("Acquire write lock to close user db failed")),
|
||||
Some(mut write_guard) => {
|
||||
write_guard.remove(user_id);
|
||||
write_guard.remove(&user_id);
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, FlowyError> {
|
||||
pub(crate) fn get_connection(&self, user_id: i64) -> Result<DBConnection, FlowyError> {
|
||||
let conn = self.get_pool(user_id)?.get()?;
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
pub(crate) fn get_pool(&self, user_id: &str) -> Result<Arc<ConnectionPool>, FlowyError> {
|
||||
pub(crate) fn get_pool(&self, user_id: i64) -> Result<Arc<ConnectionPool>, FlowyError> {
|
||||
let pool = self.open_user_db_if_need(user_id)?;
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub(crate) fn get_kv_db(&self, user_id: i64) -> Result<Arc<CollabKV>, FlowyError> {
|
||||
let kv_db = self.open_kv_db_if_need(user_id)?;
|
||||
Ok(kv_db)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref DB_MAP: RwLock<HashMap<String, Database>> = RwLock::new(HashMap::new());
|
||||
static ref DB_MAP: RwLock<HashMap<i64, Database>> = RwLock::new(HashMap::new());
|
||||
static ref KVDB_MAP: RwLock<HashMap<i64, Arc<CollabKV>>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Queryable, Identifiable, Insertable)]
|
||||
@ -108,20 +135,20 @@ impl UserTable {
|
||||
|
||||
impl std::convert::From<SignUpResponse> for UserTable {
|
||||
fn from(resp: SignUpResponse) -> Self {
|
||||
UserTable::new(resp.user_id, resp.name, resp.email, resp.token)
|
||||
UserTable::new(resp.user_id.to_string(), resp.name, resp.email, resp.token)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<SignInResponse> for UserTable {
|
||||
fn from(resp: SignInResponse) -> Self {
|
||||
UserTable::new(resp.user_id, resp.name, resp.email, resp.token)
|
||||
UserTable::new(resp.user_id.to_string(), resp.name, resp.email, resp.token)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<UserTable> for UserProfile {
|
||||
fn from(table: UserTable) -> Self {
|
||||
UserProfile {
|
||||
id: table.id,
|
||||
id: table.id.parse::<i64>().unwrap_or(0),
|
||||
email: table.email,
|
||||
name: table.name,
|
||||
token: table.token,
|
||||
@ -145,7 +172,7 @@ pub struct UserTableChangeset {
|
||||
impl UserTableChangeset {
|
||||
pub fn new(params: UpdateUserProfileParams) -> Self {
|
||||
UserTableChangeset {
|
||||
id: params.id,
|
||||
id: params.id.to_string(),
|
||||
workspace: None,
|
||||
name: params.name,
|
||||
email: params.email,
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::entities::{UserProfilePB, UserSettingPB};
|
||||
use crate::event_map::UserStatusCallback;
|
||||
|
||||
use crate::{
|
||||
errors::{ErrorCode, FlowyError},
|
||||
event_map::UserCloudService,
|
||||
notification::*,
|
||||
services::database::{UserDB, UserTable, UserTableChangeset},
|
||||
};
|
||||
use collab_persistence::CollabKV;
|
||||
use flowy_sqlite::ConnectionPool;
|
||||
use flowy_sqlite::{
|
||||
kv::KV,
|
||||
@ -13,6 +15,7 @@ use flowy_sqlite::{
|
||||
schema::{user_table, user_table::dsl},
|
||||
DBConnection, ExpressionMethods, UserDatabaseConnection,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
@ -20,6 +23,9 @@ use user_model::{
|
||||
SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
|
||||
};
|
||||
|
||||
// lazy_static! {
|
||||
// static ref ID_GEN: Mutex<UserIDGenerator> = Mutex::new(UserIDGenerator::new(1));
|
||||
// }
|
||||
pub struct UserSessionConfig {
|
||||
root_dir: String,
|
||||
|
||||
@ -59,9 +65,45 @@ impl UserSession {
|
||||
}
|
||||
|
||||
pub async fn init<C: UserStatusCallback + 'static>(&self, user_status_callback: C) {
|
||||
// if let Some(old_session) = self.get_old_session() {
|
||||
// let uid = ID_GEN.lock().next_id();
|
||||
// let _ = user_status_callback
|
||||
// .will_migrated(&old_session.token, &old_session.user_id, uid)
|
||||
// .await;
|
||||
//
|
||||
// let new_session = Session {
|
||||
// user_id: uid,
|
||||
// token: old_session.token.clone(),
|
||||
// email: old_session.email.clone(),
|
||||
// name: old_session.name.clone(),
|
||||
// };
|
||||
// self.set_session(Some(new_session)).unwrap();
|
||||
//
|
||||
// if let Ok(db) = self.db_connection() {
|
||||
// // Update db
|
||||
// let _ = db.immediate_transaction(|| {
|
||||
// // get the user data
|
||||
// let mut user = dsl::user_table
|
||||
// .filter(user_table::id.eq(&old_session.user_id))
|
||||
// .first::<UserTable>(&*db)?;
|
||||
//
|
||||
// // delete the existing row
|
||||
// let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&old_session.user_id)))
|
||||
// .execute(&*db)?;
|
||||
//
|
||||
// // insert new row
|
||||
// user.id = uid.to_string();
|
||||
// let _ = diesel::insert_into(user_table::table)
|
||||
// .values(user)
|
||||
// .execute(&*db)?;
|
||||
// Ok::<(), FlowyError>(())
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
if let Ok(session) = self.get_session() {
|
||||
let _ = user_status_callback
|
||||
.did_sign_in(&session.token, &session.user_id)
|
||||
.did_sign_in(&session.token, session.user_id)
|
||||
.await;
|
||||
}
|
||||
*self.user_status_callback.write().await = Some(Arc::new(user_status_callback));
|
||||
@ -69,7 +111,7 @@ impl UserSession {
|
||||
|
||||
pub fn db_connection(&self) -> Result<DBConnection, FlowyError> {
|
||||
let user_id = self.get_session()?.user_id;
|
||||
self.database.get_connection(&user_id)
|
||||
self.database.get_connection(user_id)
|
||||
}
|
||||
|
||||
// The caller will be not 'Sync' before of the return value,
|
||||
@ -80,7 +122,12 @@ impl UserSession {
|
||||
// let conn: PooledConnection<ConnectionManager> = pool.get()?;
|
||||
pub fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError> {
|
||||
let user_id = self.get_session()?.user_id;
|
||||
self.database.get_pool(&user_id)
|
||||
self.database.get_pool(user_id)
|
||||
}
|
||||
|
||||
pub fn get_kv_db(&self) -> Result<Arc<CollabKV>, FlowyError> {
|
||||
let user_id = self.get_session()?.user_id;
|
||||
self.database.get_kv_db(user_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
@ -106,7 +153,7 @@ impl UserSession {
|
||||
.await
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_sign_in(&user_profile.token, &user_profile.id)
|
||||
.did_sign_in(&user_profile.token, user_profile.id)
|
||||
.await;
|
||||
send_sign_in_notification()
|
||||
.payload::<UserProfilePB>(user_profile.clone().into())
|
||||
@ -140,9 +187,10 @@ impl UserSession {
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
pub async fn sign_out(&self) -> Result<(), FlowyError> {
|
||||
let session = self.get_session()?;
|
||||
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id)))
|
||||
let uid = session.user_id.to_string();
|
||||
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&uid)))
|
||||
.execute(&*(self.db_connection()?))?;
|
||||
self.database.close_user_db(&session.user_id)?;
|
||||
self.database.close_user_db(session.user_id)?;
|
||||
self.set_session(None)?;
|
||||
let _ = self
|
||||
.user_status_callback
|
||||
@ -150,7 +198,7 @@ impl UserSession {
|
||||
.await
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_expired(&session.token, &session.user_id)
|
||||
.did_expired(&session.token, session.user_id)
|
||||
.await;
|
||||
self.sign_out_on_server(&session.token).await?;
|
||||
|
||||
@ -181,7 +229,7 @@ impl UserSession {
|
||||
|
||||
pub async fn check_user(&self) -> Result<UserProfile, FlowyError> {
|
||||
let (user_id, token) = self.get_session()?.into_part();
|
||||
|
||||
let user_id = user_id.to_string();
|
||||
let user = dsl::user_table
|
||||
.filter(user_table::id.eq(&user_id))
|
||||
.first::<UserTable>(&*(self.db_connection()?))?;
|
||||
@ -192,6 +240,7 @@ impl UserSession {
|
||||
|
||||
pub async fn get_user_profile(&self) -> Result<UserProfile, FlowyError> {
|
||||
let (user_id, token) = self.get_session()?.into_part();
|
||||
let user_id = user_id.to_string();
|
||||
let user = dsl::user_table
|
||||
.filter(user_table::id.eq(&user_id))
|
||||
.first::<UserTable>(&*(self.db_connection()?))?;
|
||||
@ -212,7 +261,7 @@ impl UserSession {
|
||||
Ok(user_setting)
|
||||
}
|
||||
|
||||
pub fn user_id(&self) -> Result<String, FlowyError> {
|
||||
pub fn user_id(&self) -> Result<i64, FlowyError> {
|
||||
Ok(self.get_session()?.user_id)
|
||||
}
|
||||
|
||||
@ -288,6 +337,11 @@ impl UserSession {
|
||||
}
|
||||
}
|
||||
|
||||
// fn get_old_session(&self) -> Option<OldSession> {
|
||||
// let s = KV::get_str(&self.config.session_cache_key)?;
|
||||
// serde_json::from_str::<OldSession>(&s).ok()
|
||||
// }
|
||||
|
||||
fn is_user_login(&self, email: &str) -> bool {
|
||||
match self.get_session() {
|
||||
Ok(session) => session.email == email,
|
||||
@ -315,7 +369,7 @@ impl UserDatabaseConnection for UserSession {
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
struct Session {
|
||||
user_id: String,
|
||||
user_id: i64,
|
||||
token: String,
|
||||
email: String,
|
||||
#[serde(default)]
|
||||
@ -345,7 +399,7 @@ impl std::convert::From<SignUpResponse> for Session {
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn into_part(self) -> (String, String) {
|
||||
pub fn into_part(self) -> (i64, String) {
|
||||
(self.user_id, self.token)
|
||||
}
|
||||
}
|
||||
@ -372,3 +426,12 @@ impl std::convert::From<Session> for String {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
struct OldSession {
|
||||
user_id: String,
|
||||
token: String,
|
||||
email: String,
|
||||
#[serde(default)]
|
||||
name: String,
|
||||
}
|
||||
|
58
frontend/rust-lib/flowy-user/src/uid.rs
Normal file
58
frontend/rust-lib/flowy-user/src/uid.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
const EPOCH: u64 = 1637806706000;
|
||||
const NODE_ID_BITS: u64 = 10;
|
||||
const SEQUENCE_BITS: u64 = 12;
|
||||
const NODE_ID_SHIFT: u64 = SEQUENCE_BITS;
|
||||
const TIMESTAMP_SHIFT: u64 = NODE_ID_BITS + SEQUENCE_BITS;
|
||||
const SEQUENCE_MASK: u64 = (1 << SEQUENCE_BITS) - 1;
|
||||
|
||||
pub struct UserIDGenerator {
|
||||
node_id: u64,
|
||||
sequence: u64,
|
||||
last_timestamp: u64,
|
||||
}
|
||||
|
||||
impl UserIDGenerator {
|
||||
pub fn new(node_id: u64) -> UserIDGenerator {
|
||||
UserIDGenerator {
|
||||
node_id,
|
||||
sequence: 0,
|
||||
last_timestamp: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_id(&mut self) -> i64 {
|
||||
let timestamp = self.timestamp();
|
||||
if timestamp < self.last_timestamp {
|
||||
panic!("Clock moved backwards!");
|
||||
}
|
||||
|
||||
if timestamp == self.last_timestamp {
|
||||
self.sequence = (self.sequence + 1) & SEQUENCE_MASK;
|
||||
if self.sequence == 0 {
|
||||
self.wait_next_millis();
|
||||
}
|
||||
} else {
|
||||
self.sequence = 0;
|
||||
}
|
||||
|
||||
self.last_timestamp = timestamp;
|
||||
let id = (timestamp - EPOCH) << TIMESTAMP_SHIFT | self.node_id << NODE_ID_SHIFT | self.sequence;
|
||||
id as i64
|
||||
}
|
||||
|
||||
fn wait_next_millis(&self) {
|
||||
let mut timestamp = self.timestamp();
|
||||
while timestamp == self.last_timestamp {
|
||||
timestamp = self.timestamp();
|
||||
}
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.expect("Clock moved backwards!")
|
||||
.as_millis() as u64
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ async fn user_update_with_name() {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let user = sdk.init_user().await;
|
||||
let new_name = "hello_world".to_owned();
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).name(&new_name);
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).name(&new_name);
|
||||
let _ = UserModuleEventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
@ -53,7 +53,7 @@ async fn user_update_with_email() {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let user = sdk.init_user().await;
|
||||
let new_email = format!("{}@gmail.com", nanoid!(6));
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).email(&new_email);
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).email(&new_email);
|
||||
let _ = UserModuleEventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
@ -72,7 +72,7 @@ async fn user_update_with_password() {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let user = sdk.init_user().await;
|
||||
let new_password = "H123world!".to_owned();
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).password(&new_password);
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).password(&new_password);
|
||||
|
||||
let _ = UserModuleEventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
@ -86,7 +86,7 @@ async fn user_update_with_invalid_email() {
|
||||
let test = FlowySDKTest::default();
|
||||
let user = test.init_user().await;
|
||||
for email in invalid_email_test_case() {
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).email(&email);
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).email(&email);
|
||||
assert_eq!(
|
||||
UserModuleEventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
@ -104,7 +104,7 @@ async fn user_update_with_invalid_password() {
|
||||
let test = FlowySDKTest::default();
|
||||
let user = test.init_user().await;
|
||||
for password in invalid_password_test_case() {
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).password(&password);
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).password(&password);
|
||||
|
||||
UserModuleEventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
@ -118,7 +118,7 @@ async fn user_update_with_invalid_password() {
|
||||
async fn user_update_with_invalid_name() {
|
||||
let test = FlowySDKTest::default();
|
||||
let user = test.init_user().await;
|
||||
let request = UpdateUserProfilePayloadPB::new(&user.id).name("");
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).name("");
|
||||
UserModuleEventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
|
Reference in New Issue
Block a user