2021-07-11 15:33:19 +08:00
|
|
|
use flowy_database::{
|
|
|
|
query_dsl::*,
|
|
|
|
schema::{user_table, user_table::dsl},
|
|
|
|
DBConnection,
|
|
|
|
ExpressionMethods,
|
2021-07-13 23:08:20 +08:00
|
|
|
UserDatabaseConnection,
|
2021-07-10 16:27:20 +08:00
|
|
|
};
|
2021-07-11 15:33:19 +08:00
|
|
|
use flowy_infra::kv::KVStore;
|
2021-07-19 11:32:33 +08:00
|
|
|
|
2021-07-14 23:00:58 +08:00
|
|
|
use std::sync::{Arc, RwLock};
|
2021-07-10 16:27:20 +08:00
|
|
|
|
2021-07-11 15:33:19 +08:00
|
|
|
use crate::{
|
2021-07-16 23:18:12 +08:00
|
|
|
entities::{SignInParams, SignUpParams, UpdateUserParams, UpdateUserRequest, UserDetail},
|
2021-07-11 21:54:55 +08:00
|
|
|
errors::{ErrorBuilder, UserError, UserErrorCode},
|
2021-07-16 23:18:12 +08:00
|
|
|
event::UserEvent::*,
|
2021-07-14 21:12:52 +08:00
|
|
|
services::user_session::{database::UserDB, user_server::UserServer},
|
2021-07-19 17:37:58 +08:00
|
|
|
sql_tables::{UserTable, UserTableChangeset},
|
2021-07-11 15:33:19 +08:00
|
|
|
};
|
2021-07-16 23:18:12 +08:00
|
|
|
use flowy_dispatch::prelude::{EventDispatch, ModuleRequest, ToBytes};
|
2021-07-11 15:33:19 +08:00
|
|
|
|
2021-07-19 21:05:49 +08:00
|
|
|
const DEFAULT_WORKSPACE_NAME: &'static str = "My workspace";
|
|
|
|
const DEFAULT_WORKSPACE_DESC: &'static str = "This is your first workspace";
|
|
|
|
const DEFAULT_WORKSPACE: &'static str = "Default_Workspace";
|
|
|
|
|
2021-07-10 16:27:20 +08:00
|
|
|
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 {
|
|
|
|
database: UserDB,
|
|
|
|
config: UserSessionConfig,
|
2021-07-14 23:00:58 +08:00
|
|
|
server: Arc<dyn UserServer + Send + Sync>,
|
2021-07-18 23:56:36 +08:00
|
|
|
user_id: RwLock<Option<String>>,
|
2021-07-10 16:27:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession {
|
2021-07-14 23:00:58 +08:00
|
|
|
pub fn new<R>(config: UserSessionConfig, server: Arc<R>) -> Self
|
2021-07-10 16:27:20 +08:00
|
|
|
where
|
2021-07-11 15:33:19 +08:00
|
|
|
R: 'static + UserServer + Send + Sync,
|
2021-07-10 16:27:20 +08:00
|
|
|
{
|
|
|
|
let db = UserDB::new(&config.root_dir);
|
|
|
|
Self {
|
|
|
|
database: db,
|
|
|
|
config,
|
2021-07-14 23:00:58 +08:00
|
|
|
server,
|
2021-07-18 23:56:36 +08:00
|
|
|
user_id: RwLock::new(None),
|
2021-07-10 16:27:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 23:18:12 +08:00
|
|
|
pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
|
2021-07-18 23:56:36 +08:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-16 23:18:12 +08:00
|
|
|
self.database.get_connection(&user_id)
|
|
|
|
}
|
|
|
|
|
2021-07-19 21:05:49 +08:00
|
|
|
pub async fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError> {
|
2021-07-11 15:33:19 +08:00
|
|
|
let user = self.server.sign_in(params)?;
|
2021-07-18 23:56:36 +08:00
|
|
|
let _ = self.set_user_id(Some(user.id.clone()))?;
|
|
|
|
|
2021-07-19 21:05:49 +08:00
|
|
|
let user_table = self.save_user(user)?;
|
|
|
|
let _ = self
|
|
|
|
.create_default_workspace_if_need(&user_table.id)
|
|
|
|
.await?;
|
|
|
|
Ok(user_table)
|
2021-07-11 15:33:19 +08:00
|
|
|
}
|
|
|
|
|
2021-07-19 21:05:49 +08:00
|
|
|
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError> {
|
2021-07-11 15:33:19 +08:00
|
|
|
let user = self.server.sign_up(params)?;
|
2021-07-18 23:56:36 +08:00
|
|
|
let _ = self.set_user_id(Some(user.id.clone()))?;
|
2021-07-19 21:05:49 +08:00
|
|
|
let user_table = self.save_user(user)?;
|
|
|
|
let _ = self
|
|
|
|
.create_default_workspace_if_need(&user_table.id)
|
|
|
|
.await?;
|
|
|
|
Ok(user_table)
|
2021-07-11 15:33:19 +08:00
|
|
|
}
|
|
|
|
|
2021-07-16 23:18:12 +08:00
|
|
|
pub fn sign_out(&self) -> Result<(), UserError> {
|
2021-07-18 23:56:36 +08:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-11 17:38:03 +08:00
|
|
|
let conn = self.get_db_connection()?;
|
2021-07-11 21:54:55 +08:00
|
|
|
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&user_id))).execute(&*conn)?;
|
2021-07-11 17:38:03 +08:00
|
|
|
|
|
|
|
match self.server.sign_out(&user_id) {
|
|
|
|
Ok(_) => {},
|
|
|
|
Err(_) => {},
|
|
|
|
}
|
2021-07-18 09:03:21 +08:00
|
|
|
let _ = self.database.close_user_db(&user_id)?;
|
2021-07-18 23:56:36 +08:00
|
|
|
let _ = self.set_user_id(None)?;
|
2021-07-11 17:38:03 +08:00
|
|
|
|
|
|
|
Ok(())
|
2021-07-11 15:33:19 +08:00
|
|
|
}
|
|
|
|
|
2021-07-19 17:37:58 +08:00
|
|
|
fn save_user(&self, user: UserTable) -> Result<UserTable, UserError> {
|
2021-07-16 23:18:12 +08:00
|
|
|
let conn = self.get_db_connection()?;
|
|
|
|
let _ = diesel::insert_into(user_table::table)
|
|
|
|
.values(user.clone())
|
|
|
|
.execute(&*conn)?;
|
|
|
|
|
|
|
|
Ok(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_user(&self, params: UpdateUserParams) -> Result<UserDetail, UserError> {
|
2021-07-19 17:37:58 +08:00
|
|
|
let changeset = UserTableChangeset::new(params);
|
2021-07-14 21:12:52 +08:00
|
|
|
let conn = self.get_db_connection()?;
|
|
|
|
diesel_update_table!(user_table, changeset, conn);
|
|
|
|
|
2021-07-16 23:18:12 +08:00
|
|
|
let user_detail = self.user_detail()?;
|
2021-07-14 21:12:52 +08:00
|
|
|
Ok(user_detail)
|
|
|
|
}
|
|
|
|
|
2021-07-16 23:18:12 +08:00
|
|
|
pub fn user_detail(&self) -> Result<UserDetail, UserError> {
|
2021-07-18 23:56:36 +08:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-11 15:33:19 +08:00
|
|
|
let user = dsl::user_table
|
2021-07-11 17:38:03 +08:00
|
|
|
.filter(user_table::id.eq(&user_id))
|
2021-07-19 17:37:58 +08:00
|
|
|
.first::<UserTable>(&*(self.get_db_connection()?))?;
|
2021-07-11 15:33:19 +08:00
|
|
|
|
2021-07-11 17:38:03 +08:00
|
|
|
match self.server.get_user_info(&user_id) {
|
|
|
|
Ok(_user_detail) => {
|
|
|
|
// TODO: post latest user_detail to upper layer
|
|
|
|
},
|
|
|
|
Err(_e) => {
|
|
|
|
// log::debug!("Get user details failed. {:?}", e);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-07-11 15:33:19 +08:00
|
|
|
Ok(UserDetail::from(user))
|
|
|
|
}
|
2021-07-10 16:27:20 +08:00
|
|
|
|
2021-07-18 23:56:36 +08:00
|
|
|
pub fn set_user_id(&self, user_id: Option<String>) -> Result<(), UserError> {
|
|
|
|
log::trace!("Set user id: {:?}", user_id);
|
|
|
|
KVStore::set_str(USER_ID_CACHE_KEY, user_id.clone().unwrap_or("".to_owned()));
|
|
|
|
match self.user_id.write() {
|
|
|
|
Ok(mut write_guard) => {
|
|
|
|
*write_guard = user_id;
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
Err(e) => Err(ErrorBuilder::new(UserErrorCode::WriteCurrentIdFailed)
|
|
|
|
.error(e)
|
|
|
|
.build()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_user_id(&self) -> Result<String, UserError> {
|
2021-07-19 16:15:20 +08:00
|
|
|
let mut user_id = {
|
|
|
|
let read_guard = self.user_id.read().map_err(|e| {
|
|
|
|
ErrorBuilder::new(UserErrorCode::ReadCurrentIdFailed)
|
|
|
|
.error(e)
|
|
|
|
.build()
|
|
|
|
})?;
|
2021-07-18 23:56:36 +08:00
|
|
|
|
2021-07-19 16:15:20 +08:00
|
|
|
(*read_guard).clone()
|
|
|
|
};
|
2021-07-18 23:56:36 +08:00
|
|
|
|
|
|
|
if user_id.is_none() {
|
|
|
|
user_id = KVStore::get_str(USER_ID_CACHE_KEY);
|
2021-07-19 21:05:49 +08:00
|
|
|
let _ = self.set_user_id(user_id.clone())?;
|
2021-07-18 23:56:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
match user_id {
|
|
|
|
None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()),
|
|
|
|
Some(user_id) => Ok(user_id),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn set_current_workspace(&self, workspace_id: &str) -> Result<(), UserError> {
|
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-19 11:32:33 +08:00
|
|
|
let payload: Vec<u8> = UpdateUserRequest::new(&user_id)
|
|
|
|
.workspace(workspace_id)
|
|
|
|
.into_bytes()
|
|
|
|
.unwrap();
|
2021-07-16 23:18:12 +08:00
|
|
|
|
|
|
|
let request = ModuleRequest::new(UpdateUser).payload(payload);
|
2021-07-19 16:15:20 +08:00
|
|
|
let _ = EventDispatch::async_send(request)
|
2021-07-16 23:18:12 +08:00
|
|
|
.await
|
|
|
|
.parse::<UserDetail, UserError>()
|
2021-07-19 16:15:20 +08:00
|
|
|
.unwrap()?;
|
2021-07-16 23:18:12 +08:00
|
|
|
Ok(())
|
2021-07-10 16:27:20 +08:00
|
|
|
}
|
2021-07-19 21:05:49 +08:00
|
|
|
|
|
|
|
async fn create_default_workspace_if_need(&self, user_id: &str) -> Result<(), UserError> {
|
|
|
|
let key = format!("{}{}", user_id, DEFAULT_WORKSPACE);
|
|
|
|
if KVStore::get_bool(&key).unwrap_or(false) {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
KVStore::set_bool(&key, true);
|
|
|
|
log::debug!("Create user:{} default workspace", user_id);
|
|
|
|
let _ = self
|
|
|
|
.server
|
|
|
|
.create_workspace(DEFAULT_WORKSPACE_NAME, DEFAULT_WORKSPACE_DESC, user_id)
|
|
|
|
.await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-07-16 23:18:12 +08:00
|
|
|
}
|
2021-07-11 17:38:03 +08:00
|
|
|
|
2021-07-17 10:26:05 +08:00
|
|
|
pub fn current_user_id() -> Result<String, UserError> {
|
2021-07-18 23:56:36 +08:00
|
|
|
match KVStore::get_str(USER_ID_CACHE_KEY) {
|
2021-07-16 23:18:12 +08:00
|
|
|
None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()),
|
|
|
|
Some(user_id) => Ok(user_id),
|
2021-07-11 17:38:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-13 23:08:20 +08:00
|
|
|
impl UserDatabaseConnection for UserSession {
|
|
|
|
fn get_connection(&self) -> Result<DBConnection, String> {
|
|
|
|
self.get_db_connection().map_err(|e| format!("{:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-18 23:56:36 +08:00
|
|
|
const USER_ID_CACHE_KEY: &str = "user_id";
|