ソースを参照

config user db and user session

appflowy 3 年 前
コミット
b9d7902acb
33 ファイル変更255 行追加122 行削除
  1. 2 2
      .idea/appflowy_client.iml
  2. 5 5
      app_flowy/packages/flowy_sdk/example/macos/Podfile.lock
  3. 2 2
      rust-lib/Cargo.toml
  4. 0 0
      rust-lib/flowy-database/.env
  5. 2 2
      rust-lib/flowy-database/Cargo.toml
  6. 0 0
      rust-lib/flowy-database/diesel.toml
  7. 0 0
      rust-lib/flowy-database/migrations/.gitkeep
  8. 0 0
      rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql
  9. 0 0
      rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql
  10. 16 0
      rust-lib/flowy-database/src/errors.rs
  11. 29 0
      rust-lib/flowy-database/src/lib.rs
  12. 0 0
      rust-lib/flowy-database/src/schema.rs
  13. 0 17
      rust-lib/flowy-db/src/database.rs
  14. 0 16
      rust-lib/flowy-db/src/errors.rs
  15. 0 15
      rust-lib/flowy-db/src/lib.rs
  16. 0 13
      rust-lib/flowy-infra/src/lib.rs
  17. 0 5
      rust-lib/flowy-infra/src/sqlite/mod.rs
  18. 7 1
      rust-lib/flowy-sdk/src/lib.rs
  19. 12 1
      rust-lib/flowy-sdk/src/module.rs
  20. 1 1
      rust-lib/flowy-sqlite/Cargo.toml
  21. 4 2
      rust-lib/flowy-sqlite/src/database.rs
  22. 0 0
      rust-lib/flowy-sqlite/src/errors.rs
  23. 9 0
      rust-lib/flowy-sqlite/src/lib.rs
  24. 1 0
      rust-lib/flowy-sqlite/src/mod.rs
  25. 0 0
      rust-lib/flowy-sqlite/src/pool.rs
  26. 2 1
      rust-lib/flowy-user/Cargo.toml
  27. 0 28
      rust-lib/flowy-user/src/domain/database.rs
  28. 2 2
      rust-lib/flowy-user/src/domain/mod.rs
  29. 87 0
      rust-lib/flowy-user/src/domain/user_db.rs
  30. 48 0
      rust-lib/flowy-user/src/domain/user_session.rs
  31. 11 3
      rust-lib/flowy-user/src/errors.rs
  32. 7 4
      rust-lib/flowy-user/src/handlers/auth.rs
  33. 8 2
      rust-lib/flowy-user/src/module.rs

+ 2 - 2
.idea/appflowy_client.iml

@@ -16,8 +16,8 @@
       <sourceFolder url="file://$MODULE_DIR$/scripts/flowy-tool/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-test/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-user/tests" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-db/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-infra/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-database/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sqlite/src" isTestSource="false" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />

+ 5 - 5
app_flowy/packages/flowy_sdk/example/macos/Podfile.lock

@@ -1,5 +1,5 @@
 PODS:
-  - flowy_infra (0.0.1):
+  - flowy_sqlite (0.0.1):
     - FlutterMacOS
   - flowy_sdk (0.0.1):
     - FlutterMacOS
@@ -9,15 +9,15 @@ PODS:
     - FlutterMacOS
 
 DEPENDENCIES:
-  - flowy_infra (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra/macos`)
+  - flowy_sqlite (from `Flutter/ephemeral/.symlinks/plugins/flowy_sqlite/macos`)
   - flowy_sdk (from `Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos`)
   - FlutterMacOS (from `Flutter/ephemeral/.symlinks/flutter/darwin-x64`)
   - path_provider (from `Flutter/ephemeral/.symlinks/plugins/path_provider/macos`)
   - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
 
 EXTERNAL SOURCES:
-  flowy_infra:
-    :path: Flutter/ephemeral/.symlinks/plugins/flowy_infra/macos
+  flowy_sqlite:
+    :path: Flutter/ephemeral/.symlinks/plugins/flowy_sqlite/macos
   flowy_sdk:
     :path: Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos
   FlutterMacOS:
@@ -28,7 +28,7 @@ EXTERNAL SOURCES:
     :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
 
 SPEC CHECKSUMS:
-  flowy_infra: 6638deea1ca0baeef75156d16236123d4703161d
+  flowy_sqlite: 6638deea1ca0baeef75156d16236123d4703161d
   flowy_sdk: 12d2c047ed260a0aa8788a0b9616da46e2312025
   FlutterMacOS: 15bea8a44d2fa024068daa0140371c020b4b6ff9
   path_provider: e0848572d1d38b9a7dd099e79cf83f5b7e2cde9f

+ 2 - 2
rust-lib/Cargo.toml

@@ -8,8 +8,8 @@ members = [
   "flowy-ast",
   "flowy-derive",
   "flowy-test",
-  "flowy-infra",
-  "flowy-db",
+    "flowy-sqlite",
+    "flowy-database",
 ]
 
 [profile.dev]

+ 0 - 0
rust-lib/flowy-db/.env → rust-lib/flowy-database/.env


+ 2 - 2
rust-lib/flowy-db/Cargo.toml → rust-lib/flowy-database/Cargo.toml

@@ -1,5 +1,5 @@
 [package]
-name = "flowy-db"
+name = "flowy-database"
 version = "0.1.0"
 edition = "2018"
 
@@ -9,4 +9,4 @@ edition = "2018"
 diesel = {version = "1.4.7", features = ["sqlite"]}
 diesel_derives = {version = "1.4.1", features = ["sqlite"]}
 diesel_migrations = {version = "1.4.0", features = ["sqlite"]}
-flowy-infra = {path = "../flowy-infra"}
+flowy-sqlite = {path = "../flowy-sqlite" }

+ 0 - 0
rust-lib/flowy-db/diesel.toml → rust-lib/flowy-database/diesel.toml


+ 0 - 0
rust-lib/flowy-db/migrations/.gitkeep → rust-lib/flowy-database/migrations/.gitkeep


+ 0 - 0
rust-lib/flowy-db/migrations/2021-07-09-063045_flowy-user/down.sql → rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql


+ 0 - 0
rust-lib/flowy-db/migrations/2021-07-09-063045_flowy-user/up.sql → rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql


+ 16 - 0
rust-lib/flowy-database/src/errors.rs

@@ -0,0 +1,16 @@
+use flowy_sqlite::Error;
+use std::io;
+
+#[derive(Debug)]
+pub enum DataBaseError {
+    InitError(String),
+    IOError(String),
+}
+
+impl std::convert::From<flowy_sqlite::Error> for DataBaseError {
+    fn from(error: flowy_sqlite::Error) -> Self { DataBaseError::InitError(format!("{:?}", error)) }
+}
+
+impl std::convert::From<io::Error> for DataBaseError {
+    fn from(error: io::Error) -> Self { DataBaseError::IOError(format!("{:?}", error)) }
+}

+ 29 - 0
rust-lib/flowy-database/src/lib.rs

@@ -0,0 +1,29 @@
+mod errors;
+mod schema;
+
+#[macro_use]
+extern crate diesel;
+#[macro_use]
+extern crate diesel_derives;
+#[macro_use]
+extern crate diesel_migrations;
+
+pub use errors::*;
+pub use flowy_sqlite::{DBConnection, DataBase};
+
+use diesel_migrations::*;
+use flowy_sqlite::PoolConfig;
+use std::path::Path;
+
+embed_migrations!("../flowy-database/migrations/");
+pub const DB_NAME: &str = "flowy-database.db";
+
+pub fn init(storage_path: &str) -> Result<DataBase, DataBaseError> {
+    if !Path::new(storage_path).exists() {
+        std::fs::create_dir_all(storage_path)?;
+    }
+
+    let pool_config = PoolConfig::default();
+    let database = DataBase::new(storage_path, DB_NAME, pool_config)?;
+    Ok(database)
+}

+ 0 - 0
rust-lib/flowy-db/src/schema.rs → rust-lib/flowy-database/src/schema.rs


+ 0 - 17
rust-lib/flowy-db/src/database.rs

@@ -1,17 +0,0 @@
-use crate::errors::FlowyDBError;
-use diesel_migrations::*;
-use flowy_infra::sqlite::*;
-use std::path::Path;
-
-embed_migrations!("../flowy-db/migrations/");
-pub const DB_NAME: &str = "flowy-database.db";
-
-pub fn init(storage_path: &str) -> Result<DataBase, FlowyDBError> {
-    if !Path::new(storage_path).exists() {
-        std::fs::create_dir_all(storage_path)?;
-    }
-
-    let pool_config = PoolConfig::default();
-    let database = DataBase::new(storage_path, DB_NAME, pool_config)?;
-    Ok(database)
-}

+ 0 - 16
rust-lib/flowy-db/src/errors.rs

@@ -1,16 +0,0 @@
-use flowy_infra::Error;
-use std::io;
-
-#[derive(Debug)]
-pub enum FlowyDBError {
-    InitError(String),
-    IOError(String),
-}
-
-impl std::convert::From<flowy_infra::Error> for FlowyDBError {
-    fn from(error: flowy_infra::Error) -> Self { FlowyDBError::InitError(format!("{:?}", error)) }
-}
-
-impl std::convert::From<io::Error> for FlowyDBError {
-    fn from(error: io::Error) -> Self { FlowyDBError::IOError(format!("{:?}", error)) }
-}

+ 0 - 15
rust-lib/flowy-db/src/lib.rs

@@ -1,15 +0,0 @@
-mod database;
-mod errors;
-mod schema;
-
-#[macro_use]
-extern crate diesel;
-#[macro_use]
-extern crate diesel_derives;
-#[macro_use]
-extern crate diesel_migrations;
-
-pub use flowy_infra::sqlite::DataBase;
-
-pub use database::init;
-pub use errors::*;

+ 0 - 13
rust-lib/flowy-infra/src/lib.rs

@@ -1,13 +0,0 @@
-#[allow(deprecated, clippy::large_enum_variant)]
-mod errors;
-pub mod sqlite;
-
-pub use errors::{Error, ErrorKind, Result};
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn it_works() {
-        assert_eq!(2 + 2, 4);
-    }
-}

+ 0 - 5
rust-lib/flowy-infra/src/sqlite/mod.rs

@@ -1,5 +0,0 @@
-mod database;
-mod pool;
-
-pub use database::*;
-pub use pool::*;

+ 7 - 1
rust-lib/flowy-sdk/src/lib.rs

@@ -3,6 +3,7 @@ pub use module::*;
 
 use flowy_dispatch::prelude::*;
 use module::build_modules;
+
 pub struct FlowySDK {}
 
 impl FlowySDK {
@@ -10,6 +11,11 @@ impl FlowySDK {
 
     pub fn init(path: &str) {
         tracing::trace!("🔥 Root path: {}", path);
-        EventDispatch::construct(|| build_modules());
+
+        let config = ModuleConfig {
+            root: path.to_string(),
+        };
+
+        EventDispatch::construct(|| build_modules(config));
     }
 }

+ 12 - 1
rust-lib/flowy-sdk/src/module.rs

@@ -1,3 +1,14 @@
 use flowy_dispatch::prelude::Module;
+use flowy_user::prelude::user_session::{UserSession, UserSessionConfig};
+use std::sync::Arc;
 
-pub fn build_modules() -> Vec<Module> { vec![flowy_user::module::create()] }
+pub struct ModuleConfig {
+    pub root: String,
+}
+
+pub fn build_modules(config: ModuleConfig) -> Vec<Module> {
+    let user_config = UserSessionConfig::new(&config.root);
+    let user_session = Arc::new(UserSession::new(user_config));
+
+    vec![flowy_user::module::create(user_session)]
+}

+ 1 - 1
rust-lib/flowy-infra/Cargo.toml → rust-lib/flowy-sqlite/Cargo.toml

@@ -1,5 +1,5 @@
 [package]
-name = "flowy-infra"
+name = "flowy-sqlite"
 version = "0.1.0"
 edition = "2018"
 

+ 4 - 2
rust-lib/flowy-infra/src/sqlite/database.rs → rust-lib/flowy-sqlite/src/database.rs

@@ -1,6 +1,6 @@
 use crate::{
     errors::*,
-    sqlite::pool::{ConnectionManager, ConnectionPool, PoolConfig},
+    pool::{ConnectionManager, ConnectionPool, PoolConfig},
 };
 use r2d2::PooledConnection;
 
@@ -9,6 +9,8 @@ pub struct DataBase {
     pool: ConnectionPool,
 }
 
+pub type DBConnection = PooledConnection<ConnectionManager>;
+
 impl DataBase {
     pub fn new(dir: &str, name: &str, pool_config: PoolConfig) -> Result<Self> {
         let uri = db_file_uri(dir, name);
@@ -18,7 +20,7 @@ impl DataBase {
 
     pub fn get_uri(&self) -> &str { &self.uri }
 
-    pub fn get_conn(&self) -> Result<PooledConnection<ConnectionManager>> {
+    pub fn get_connection(&self) -> Result<DBConnection> {
         let conn = self.pool.get()?;
         Ok(conn)
     }

+ 0 - 0
rust-lib/flowy-infra/src/errors.rs → rust-lib/flowy-sqlite/src/errors.rs


+ 9 - 0
rust-lib/flowy-sqlite/src/lib.rs

@@ -0,0 +1,9 @@
+mod database;
+#[allow(deprecated, clippy::large_enum_variant)]
+mod errors;
+mod pool;
+
+pub use database::*;
+pub use pool::*;
+
+pub use errors::{Error, ErrorKind, Result};

+ 1 - 0
rust-lib/flowy-sqlite/src/mod.rs

@@ -0,0 +1 @@
+

+ 0 - 0
rust-lib/flowy-infra/src/sqlite/pool.rs → rust-lib/flowy-sqlite/src/pool.rs


+ 2 - 1
rust-lib/flowy-user/Cargo.toml

@@ -10,7 +10,8 @@ derive_more = {version = "0.99", features = ["display"]}
 flowy-dispatch = { path = "../flowy-dispatch" }
 flowy-log = { path = "../flowy-log" }
 flowy-derive = { path = "../flowy-derive" }
-flowy-db = { path = "../flowy-db" }
+flowy-database = { path = "../flowy-database" }
+flowy-sqlite = { path = "../flowy-sqlite" }
 
 tracing = { version = "0.1", features = ["log"] }
 bytes = "1.0"

+ 0 - 28
rust-lib/flowy-user/src/domain/database.rs

@@ -1,28 +0,0 @@
-use crate::errors::UserError;
-use flowy_db::DataBase;
-use lazy_static::lazy_static;
-use std::sync::{
-    atomic::{AtomicBool, Ordering},
-    RwLock,
-};
-
-lazy_static! {
-    pub static ref DB: RwLock<Option<DataBase>> = RwLock::new(None);
-}
-
-static DB_INIT: AtomicBool = AtomicBool::new(false);
-
-pub fn init_user_db(dir: &str) -> Result<(), UserError> {
-    let database = flowy_db::init(dir)?;
-    *(DB.write()?) = Some(database);
-    Ok(())
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    #[test]
-    fn init_db_test() {
-        // init_user_db(".").unwrap();
-    }
-}

+ 2 - 2
rust-lib/flowy-user/src/domain/mod.rs

@@ -1,4 +1,4 @@
 pub use user::*;
-
-mod database;
 pub mod user;
+pub mod user_db;
+pub mod user_session;

+ 87 - 0
rust-lib/flowy-user/src/domain/user_db.rs

@@ -0,0 +1,87 @@
+use crate::errors::UserError;
+use flowy_database::{DBConnection, DataBase};
+use lazy_static::lazy_static;
+use std::{
+    cell::RefCell,
+    sync::{
+        atomic::{AtomicBool, Ordering},
+        RwLock,
+    },
+};
+
+thread_local! {
+    static USER_ID: RefCell<Option<String>> = RefCell::new(None);
+}
+fn set_user_id(user_id: Option<String>) {
+    USER_ID.with(|id| {
+        *id.borrow_mut() = user_id;
+    });
+}
+fn get_user_id() -> Option<String> { USER_ID.with(|id| id.borrow().clone()) }
+
+static IS_USER_DB_INIT: AtomicBool = AtomicBool::new(false);
+
+lazy_static! {
+    static ref USER_DB_INNER: RwLock<Option<DataBase>> = RwLock::new(None);
+}
+
+pub(crate) struct UserDB {
+    db_dir: String,
+}
+
+impl UserDB {
+    pub(crate) fn new(db_dir: &str) -> Self {
+        Self {
+            db_dir: db_dir.to_owned(),
+        }
+    }
+
+    fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
+        let user_dir = format!("{}/{}", self.db_dir, user_id);
+        let database = flowy_database::init(&user_dir)?;
+        let mut write_guard = USER_DB_INNER.write()?;
+        set_user_id(Some(user_id.to_owned()));
+        *(write_guard) = Some(database);
+        IS_USER_DB_INIT.store(true, Ordering::SeqCst);
+        Ok(())
+    }
+
+    pub(crate) fn close_user_db(&mut self) -> Result<(), UserError> {
+        let mut write_guard = USER_DB_INNER.write()?;
+        *write_guard = None;
+        set_user_id(None);
+        IS_USER_DB_INIT.store(false, Ordering::SeqCst);
+        Ok(())
+    }
+
+    pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, UserError> {
+        if !IS_USER_DB_INIT.load(Ordering::SeqCst) {
+            let _ = self.open_user_db(user_id);
+        }
+
+        let thread_user_id = get_user_id();
+        if thread_user_id != Some(user_id.to_owned()) {
+            let msg = format!(
+                "DataBase owner does not match. origin: {:?}, current: {}",
+                thread_user_id, user_id
+            );
+            log::error!("{}", msg);
+            return Err(UserError::DBConnection(msg));
+        }
+
+        let read_guard = USER_DB_INNER.read()?;
+        match read_guard.as_ref() {
+            None => Err(UserError::DBNotInit),
+            Some(database) => Ok(database.get_connection()?),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    #[test]
+    fn init_db_test() {
+        // init_user_db(".").unwrap();
+    }
+}

+ 48 - 0
rust-lib/flowy-user/src/domain/user_session.rs

@@ -0,0 +1,48 @@
+use crate::{domain::user_db::UserDB, errors::UserError};
+use flowy_sqlite::DBConnection;
+use lazy_static::lazy_static;
+use std::sync::RwLock;
+
+lazy_static! {
+    pub static ref CURRENT_USER_ID: RwLock<Option<String>> = RwLock::new(None);
+}
+fn get_current_user_id() -> Result<Option<String>, UserError> {
+    match CURRENT_USER_ID.read() {
+        Ok(read_guard) => Ok((*read_guard).clone()),
+        Err(e) => {
+            log::error!("Get current user id failed: {:?}", e);
+            Err(e.into())
+        },
+    }
+}
+
+pub struct UserSessionConfig {
+    root_dir: String,
+}
+
+impl UserSessionConfig {
+    pub fn new(root_dir: &str) -> Self {
+        Self {
+            root_dir: root_dir.to_owned(),
+        }
+    }
+}
+
+pub struct UserSession {
+    db: UserDB,
+    config: UserSessionConfig,
+}
+
+impl UserSession {
+    pub fn new(config: UserSessionConfig) -> Self {
+        let db = UserDB::new(&config.root_dir);
+        Self { db, config }
+    }
+
+    pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
+        match get_current_user_id()? {
+            None => Err(UserError::UserNotLogin),
+            Some(user_id) => self.db.get_connection(&user_id),
+        }
+    }
+}

+ 11 - 3
rust-lib/flowy-user/src/errors.rs

@@ -1,15 +1,23 @@
+use flowy_database::DataBaseError;
 use std::sync::PoisonError;
 
 #[derive(Debug)]
 pub enum UserError {
-    DBInitFail(String),
+    DBInit(String),
+    DBNotInit,
+    UserNotLogin,
+    DBConnection(String),
     PoisonError(String),
 }
 
-impl std::convert::From<flowy_db::FlowyDBError> for UserError {
-    fn from(error: flowy_db::FlowyDBError) -> Self { UserError::DBInitFail(format!("{:?}", error)) }
+impl std::convert::From<DataBaseError> for UserError {
+    fn from(error: DataBaseError) -> Self { UserError::DBInit(format!("{:?}", error)) }
 }
 
 impl<T> std::convert::From<PoisonError<T>> for UserError {
     fn from(error: PoisonError<T>) -> Self { UserError::PoisonError(format!("{:?}", error)) }
 }
+
+impl std::convert::From<flowy_sqlite::Error> for UserError {
+    fn from(e: flowy_sqlite::Error) -> Self { UserError::DBConnection(format!("{:?}", e)) }
+}

+ 7 - 4
rust-lib/flowy-user/src/handlers/auth.rs

@@ -1,6 +1,6 @@
-use crate::domain::user::*;
+use crate::domain::{user::*, user_session::UserSession};
 use flowy_dispatch::prelude::*;
-use std::convert::TryInto;
+use std::{convert::TryInto, sync::Arc};
 
 // tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
 #[tracing::instrument(
@@ -19,12 +19,15 @@ pub async fn user_sign_in(data: Data<SignInRequest>) -> ResponseResult<SignInRes
 
 #[tracing::instrument(
     name = "user_sign_up",
-    skip(data),
+    skip(data, session),
     fields(
     email = %data.email,
     )
 )]
-pub async fn user_sign_up(data: Data<SignUpRequest>) -> ResponseResult<SignUpResponse, String> {
+pub async fn user_sign_up(
+    data: Data<SignUpRequest>,
+    session: ModuleData<Arc<UserSession>>,
+) -> ResponseResult<SignUpResponse, String> {
     let _params: SignUpParams = data.into_inner().try_into()?;
     // TODO: user sign up
 

+ 8 - 2
rust-lib/flowy-user/src/module.rs

@@ -1,10 +1,16 @@
 use flowy_dispatch::prelude::*;
 
-use crate::{event::UserEvent, handlers::*};
+use crate::{
+    domain::{user_db::*, user_session::UserSession},
+    event::UserEvent,
+    handlers::*,
+};
+use std::sync::Arc;
 
-pub fn create() -> Module {
+pub fn create(user_session: Arc<UserSession>) -> Module {
     Module::new()
         .name("Flowy-User")
+        .data(user_session)
         .event(UserEvent::SignIn, user_sign_in)
         .event(UserEvent::SignUp, user_sign_up)
 }