2021-08-20 06:38:03 +00:00
|
|
|
use crate::{
|
|
|
|
entities::{SignInParams, SignUpParams, UpdateUserParams, UpdateUserRequest, UserDetail},
|
|
|
|
errors::{ErrorBuilder, UserErrCode, UserError},
|
|
|
|
event::UserEvent::*,
|
|
|
|
services::{
|
|
|
|
user::{construct_server, database::UserDB, UserServer},
|
|
|
|
workspace::WorkspaceAction,
|
|
|
|
},
|
|
|
|
sql_tables::{UserTable, UserTableChangeset},
|
|
|
|
};
|
2021-08-20 14:00:03 +00:00
|
|
|
use bytes::Bytes;
|
2021-07-11 07:33:19 +00:00
|
|
|
use flowy_database::{
|
|
|
|
query_dsl::*,
|
|
|
|
schema::{user_table, user_table::dsl},
|
|
|
|
DBConnection,
|
|
|
|
ExpressionMethods,
|
2021-07-13 15:08:20 +00:00
|
|
|
UserDatabaseConnection,
|
2021-07-10 08:27:20 +00:00
|
|
|
};
|
2021-08-20 06:38:03 +00:00
|
|
|
use flowy_dispatch::prelude::{EventDispatch, ModuleRequest, ToBytes};
|
2021-07-11 07:33:19 +00:00
|
|
|
use flowy_infra::kv::KVStore;
|
2021-07-14 15:00:58 +00:00
|
|
|
use std::sync::{Arc, RwLock};
|
2021-07-10 08:27:20 +00:00
|
|
|
|
2021-07-19 13:05:49 +00: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 08:27:20 +00: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-08-20 06:38:03 +00:00
|
|
|
workspace: Arc<dyn WorkspaceAction + Send + Sync>,
|
2021-07-14 15:00:58 +00:00
|
|
|
server: Arc<dyn UserServer + Send + Sync>,
|
2021-07-18 15:56:36 +00:00
|
|
|
user_id: RwLock<Option<String>>,
|
2021-07-10 08:27:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession {
|
2021-08-20 06:38:03 +00:00
|
|
|
pub fn new<R>(config: UserSessionConfig, workspace: Arc<R>) -> Self
|
2021-07-10 08:27:20 +00:00
|
|
|
where
|
2021-08-20 06:38:03 +00:00
|
|
|
R: 'static + WorkspaceAction + Send + Sync,
|
2021-07-10 08:27:20 +00:00
|
|
|
{
|
|
|
|
let db = UserDB::new(&config.root_dir);
|
2021-08-20 06:38:03 +00:00
|
|
|
let server = construct_server();
|
2021-07-10 08:27:20 +00:00
|
|
|
Self {
|
|
|
|
database: db,
|
|
|
|
config,
|
2021-08-20 06:38:03 +00:00
|
|
|
workspace,
|
2021-07-14 15:00:58 +00:00
|
|
|
server,
|
2021-07-18 15:56:36 +00:00
|
|
|
user_id: RwLock::new(None),
|
2021-07-10 08:27:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 15:18:12 +00:00
|
|
|
pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
|
2021-07-18 15:56:36 +00:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-16 15:18:12 +00:00
|
|
|
self.database.get_connection(&user_id)
|
|
|
|
}
|
|
|
|
|
2021-07-19 13:05:49 +00:00
|
|
|
pub async fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError> {
|
2021-08-20 06:38:03 +00:00
|
|
|
let resp = self.server.sign_in(params).await?;
|
|
|
|
let _ = self.set_user_id(Some(resp.uid.clone()))?;
|
|
|
|
let user_table = self.save_user(resp.into()).await?;
|
2021-07-18 15:56:36 +00:00
|
|
|
|
2021-07-19 13:05:49 +00:00
|
|
|
Ok(user_table)
|
2021-07-11 07:33:19 +00:00
|
|
|
}
|
|
|
|
|
2021-07-19 13:05:49 +00:00
|
|
|
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError> {
|
2021-08-20 06:38:03 +00:00
|
|
|
let resp = self.server.sign_up(params).await?;
|
|
|
|
let _ = self.set_user_id(Some(resp.uid.clone()))?;
|
|
|
|
let user_table = self.save_user(resp.into()).await?;
|
2021-07-24 07:05:47 +00:00
|
|
|
|
2021-07-19 13:05:49 +00:00
|
|
|
Ok(user_table)
|
2021-07-11 07:33:19 +00:00
|
|
|
}
|
|
|
|
|
2021-07-16 15:18:12 +00:00
|
|
|
pub fn sign_out(&self) -> Result<(), UserError> {
|
2021-07-18 15:56:36 +00:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-11 09:38:03 +00:00
|
|
|
let conn = self.get_db_connection()?;
|
2021-07-11 13:54:55 +00:00
|
|
|
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&user_id))).execute(&*conn)?;
|
2021-08-20 06:38:03 +00:00
|
|
|
let _ = self.server.sign_out(&user_id);
|
2021-07-18 01:03:21 +00:00
|
|
|
let _ = self.database.close_user_db(&user_id)?;
|
2021-07-18 15:56:36 +00:00
|
|
|
let _ = self.set_user_id(None)?;
|
2021-07-11 09:38:03 +00:00
|
|
|
|
|
|
|
Ok(())
|
2021-07-11 07:33:19 +00:00
|
|
|
}
|
|
|
|
|
2021-08-27 15:53:53 +00:00
|
|
|
async fn save_user(&self, user: UserTable) -> Result<UserTable, UserError> {
|
2021-07-16 15:18:12 +00: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 09:37:58 +00:00
|
|
|
let changeset = UserTableChangeset::new(params);
|
2021-07-14 13:12:52 +00:00
|
|
|
let conn = self.get_db_connection()?;
|
|
|
|
diesel_update_table!(user_table, changeset, conn);
|
2021-07-16 15:18:12 +00:00
|
|
|
let user_detail = self.user_detail()?;
|
2021-07-14 13:12:52 +00:00
|
|
|
Ok(user_detail)
|
|
|
|
}
|
|
|
|
|
2021-07-16 15:18:12 +00:00
|
|
|
pub fn user_detail(&self) -> Result<UserDetail, UserError> {
|
2021-07-18 15:56:36 +00:00
|
|
|
let user_id = self.get_user_id()?;
|
2021-07-11 07:33:19 +00:00
|
|
|
let user = dsl::user_table
|
2021-07-11 09:38:03 +00:00
|
|
|
.filter(user_table::id.eq(&user_id))
|
2021-07-19 09:37:58 +00:00
|
|
|
.first::<UserTable>(&*(self.get_db_connection()?))?;
|
2021-07-11 07:33:19 +00:00
|
|
|
|
2021-08-20 06:38:03 +00:00
|
|
|
let _ = self.server.get_user_info(&user_id);
|
2021-07-11 09:38:03 +00:00
|
|
|
|
2021-07-11 07:33:19 +00:00
|
|
|
Ok(UserDetail::from(user))
|
|
|
|
}
|
2021-07-10 08:27:20 +00:00
|
|
|
|
2021-07-18 15:56:36 +00: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(())
|
|
|
|
},
|
2021-07-25 00:13:59 +00:00
|
|
|
Err(e) => Err(ErrorBuilder::new(UserErrCode::WriteCurrentIdFailed)
|
2021-07-18 15:56:36 +00:00
|
|
|
.error(e)
|
|
|
|
.build()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 09:30:33 +00:00
|
|
|
pub fn get_user_dir(&self) -> Result<String, UserError> {
|
|
|
|
let user_id = self.get_user_id()?;
|
|
|
|
Ok(format!("{}/{}", self.config.root_dir, user_id))
|
|
|
|
}
|
|
|
|
|
2021-07-18 15:56:36 +00:00
|
|
|
pub fn get_user_id(&self) -> Result<String, UserError> {
|
2021-07-19 08:15:20 +00:00
|
|
|
let mut user_id = {
|
|
|
|
let read_guard = self.user_id.read().map_err(|e| {
|
2021-07-25 00:13:59 +00:00
|
|
|
ErrorBuilder::new(UserErrCode::ReadCurrentIdFailed)
|
2021-07-19 08:15:20 +00:00
|
|
|
.error(e)
|
|
|
|
.build()
|
|
|
|
})?;
|
2021-07-18 15:56:36 +00:00
|
|
|
|
2021-07-19 08:15:20 +00:00
|
|
|
(*read_guard).clone()
|
|
|
|
};
|
2021-07-18 15:56:36 +00:00
|
|
|
|
|
|
|
if user_id.is_none() {
|
|
|
|
user_id = KVStore::get_str(USER_ID_CACHE_KEY);
|
2021-07-19 13:05:49 +00:00
|
|
|
let _ = self.set_user_id(user_id.clone())?;
|
2021-07-18 15:56:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
match user_id {
|
2021-07-25 00:13:59 +00:00
|
|
|
None => Err(ErrorBuilder::new(UserErrCode::UserNotLoginYet).build()),
|
2021-07-18 15:56:36 +00:00
|
|
|
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-08-20 14:00:03 +00:00
|
|
|
let payload: Bytes = UpdateUserRequest::new(&user_id)
|
2021-07-19 03:32:33 +00:00
|
|
|
.workspace(workspace_id)
|
|
|
|
.into_bytes()
|
|
|
|
.unwrap();
|
2021-07-16 15:18:12 +00:00
|
|
|
|
|
|
|
let request = ModuleRequest::new(UpdateUser).payload(payload);
|
2021-07-19 08:15:20 +00:00
|
|
|
let _ = EventDispatch::async_send(request)
|
2021-07-16 15:18:12 +00:00
|
|
|
.await
|
|
|
|
.parse::<UserDetail, UserError>()
|
2021-07-19 08:15:20 +00:00
|
|
|
.unwrap()?;
|
2021-07-16 15:18:12 +00:00
|
|
|
Ok(())
|
2021-07-10 08:27:20 +00:00
|
|
|
}
|
2021-07-19 13:05:49 +00:00
|
|
|
|
2021-07-24 07:05:47 +00:00
|
|
|
async fn create_default_workspace_if_need(&self, user_id: &str) -> Result<String, UserError> {
|
2021-07-19 13:05:49 +00:00
|
|
|
let key = format!("{}{}", user_id, DEFAULT_WORKSPACE);
|
|
|
|
if KVStore::get_bool(&key).unwrap_or(false) {
|
2021-07-25 00:13:59 +00:00
|
|
|
return Err(ErrorBuilder::new(UserErrCode::DefaultWorkspaceAlreadyExist).build());
|
2021-07-19 13:05:49 +00:00
|
|
|
}
|
|
|
|
KVStore::set_bool(&key, true);
|
|
|
|
log::debug!("Create user:{} default workspace", user_id);
|
2021-07-24 07:05:47 +00:00
|
|
|
let workspace_id = self
|
2021-08-20 06:38:03 +00:00
|
|
|
.workspace
|
2021-07-19 13:05:49 +00:00
|
|
|
.create_workspace(DEFAULT_WORKSPACE_NAME, DEFAULT_WORKSPACE_DESC, user_id)
|
|
|
|
.await?;
|
2021-07-24 07:05:47 +00:00
|
|
|
Ok(workspace_id)
|
2021-07-19 13:05:49 +00:00
|
|
|
}
|
2021-07-16 15:18:12 +00:00
|
|
|
}
|
2021-07-11 09:38:03 +00:00
|
|
|
|
2021-07-17 02:26:05 +00:00
|
|
|
pub fn current_user_id() -> Result<String, UserError> {
|
2021-07-18 15:56:36 +00:00
|
|
|
match KVStore::get_str(USER_ID_CACHE_KEY) {
|
2021-07-25 00:13:59 +00:00
|
|
|
None => Err(ErrorBuilder::new(UserErrCode::UserNotLoginYet).build()),
|
2021-07-16 15:18:12 +00:00
|
|
|
Some(user_id) => Ok(user_id),
|
2021-07-11 09:38:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-13 15:08:20 +00:00
|
|
|
impl UserDatabaseConnection for UserSession {
|
|
|
|
fn get_connection(&self) -> Result<DBConnection, String> {
|
|
|
|
self.get_db_connection().map_err(|e| format!("{:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-18 15:56:36 +00:00
|
|
|
const USER_ID_CACHE_KEY: &str = "user_id";
|