2021-08-20 06:38:03 +00:00
|
|
|
use crate::{
|
2021-08-29 14:00:42 +00:00
|
|
|
entities::{SignInParams, SignUpParams, UpdateUserParams, UserDetail},
|
2021-08-30 14:44:17 +00:00
|
|
|
errors::{ErrorBuilder, ErrorCode, UserError},
|
2021-09-01 08:37:46 +00:00
|
|
|
services::user::{construct_user_server, database::UserDB},
|
2021-08-20 06:38:03 +00:00
|
|
|
sql_tables::{UserTable, UserTableChangeset},
|
|
|
|
};
|
2021-08-29 14:00:42 +00:00
|
|
|
|
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-29 14:00:42 +00:00
|
|
|
|
2021-09-01 08:37:46 +00:00
|
|
|
use crate::services::server::Server;
|
2021-07-11 07:33:19 +00:00
|
|
|
use flowy_infra::kv::KVStore;
|
2021-08-31 15:01:46 +00:00
|
|
|
use flowy_sqlite::ConnectionPool;
|
2021-09-01 03:21:42 +00:00
|
|
|
use parking_lot::RwLock;
|
|
|
|
use serde::{Deserialize, Serialize};
|
2021-09-01 08:37:46 +00:00
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
use std::sync::Arc;
|
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-30 08:18:58 +00:00
|
|
|
#[allow(dead_code)]
|
2021-09-01 08:08:32 +00:00
|
|
|
server: Server,
|
2021-09-01 03:21:42 +00:00
|
|
|
session: RwLock<Option<Session>>,
|
2021-07-10 08:27:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession {
|
2021-08-31 15:01:46 +00:00
|
|
|
pub fn new(config: UserSessionConfig) -> Self {
|
2021-07-10 08:27:20 +00:00
|
|
|
let db = UserDB::new(&config.root_dir);
|
2021-08-31 15:01:46 +00:00
|
|
|
let server = construct_user_server();
|
2021-07-10 08:27:20 +00:00
|
|
|
Self {
|
|
|
|
database: db,
|
|
|
|
config,
|
2021-07-14 15:00:58 +00:00
|
|
|
server,
|
2021-09-01 03:21:42 +00:00
|
|
|
session: 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-09-01 03:21:42 +00:00
|
|
|
let user_id = self.get_session()?.user_id;
|
2021-07-16 15:18:12 +00:00
|
|
|
self.database.get_connection(&user_id)
|
|
|
|
}
|
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
// The caller will be not 'Sync' before of the return value,
|
|
|
|
// PooledConnection<ConnectionManager> is not sync. You can use
|
|
|
|
// db_connection_pool function to require the ConnectionPool that is 'Sync'.
|
|
|
|
//
|
|
|
|
// let pool = self.db_connection_pool()?;
|
|
|
|
// let conn: PooledConnection<ConnectionManager> = pool.get()?;
|
2021-08-31 15:01:46 +00:00
|
|
|
pub fn db_connection_pool(&self) -> Result<Arc<ConnectionPool>, UserError> {
|
2021-09-01 03:21:42 +00:00
|
|
|
let user_id = self.get_session()?.user_id;
|
2021-08-31 15:01:46 +00:00
|
|
|
self.database.get_pool(&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?;
|
2021-09-01 03:21:42 +00:00
|
|
|
let session = Session::new(&resp.uid, &resp.token);
|
|
|
|
let _ = self.set_session(Some(session))?;
|
2021-08-20 06:38:03 +00:00
|
|
|
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?;
|
2021-09-01 03:21:42 +00:00
|
|
|
let session = Session::new(&resp.uid, &resp.token);
|
|
|
|
let _ = self.set_session(Some(session))?;
|
2021-08-20 06:38:03 +00:00
|
|
|
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-08-31 09:25:08 +00:00
|
|
|
pub async fn sign_out(&self) -> Result<(), UserError> {
|
2021-09-01 08:08:32 +00:00
|
|
|
let session = self.get_session()?;
|
|
|
|
match self.server.sign_out(&session.token).await {
|
2021-08-31 09:25:08 +00:00
|
|
|
Ok(_) => {},
|
|
|
|
Err(e) => log::error!("Sign out failed: {:?}", e),
|
|
|
|
}
|
|
|
|
|
2021-07-11 09:38:03 +00:00
|
|
|
let conn = self.get_db_connection()?;
|
2021-08-31 09:25:08 +00:00
|
|
|
let _ =
|
2021-09-01 08:08:32 +00:00
|
|
|
diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*conn)?;
|
|
|
|
let _ = self.server.sign_out(&session.token);
|
|
|
|
let _ = self.database.close_user_db(&session.user_id)?;
|
2021-09-01 03:21:42 +00:00
|
|
|
let _ = self.set_session(None)?;
|
2021-07-11 09:38:03 +00:00
|
|
|
|
|
|
|
Ok(())
|
2021-07-11 07:33:19 +00:00
|
|
|
}
|
|
|
|
|
2021-08-31 15:01:46 +00:00
|
|
|
pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), UserError> {
|
2021-09-01 09:57:06 +00:00
|
|
|
let session = self.get_session()?;
|
|
|
|
match self
|
|
|
|
.server
|
|
|
|
.update_user(&session.token, params.clone())
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
Ok(_) => {},
|
|
|
|
Err(e) => {
|
|
|
|
// TODO: retry?
|
|
|
|
log::error!("update user profile failed: {:?}", e);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
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-08-31 15:01:46 +00:00
|
|
|
Ok(())
|
2021-07-14 13:12:52 +00:00
|
|
|
}
|
|
|
|
|
2021-08-31 15:01:46 +00:00
|
|
|
pub async fn user_detail(&self) -> Result<UserDetail, UserError> {
|
2021-09-01 08:37:46 +00:00
|
|
|
let session = self.get_session()?;
|
|
|
|
let token = session.token;
|
2021-08-31 15:01:46 +00:00
|
|
|
let server = self.server.clone();
|
|
|
|
tokio::spawn(async move {
|
|
|
|
match server.get_user_detail(&token).await {
|
|
|
|
Ok(user_detail) => {
|
|
|
|
//
|
|
|
|
log::info!("{:?}", user_detail);
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
//
|
|
|
|
log::info!("{:?}", e);
|
|
|
|
},
|
|
|
|
}
|
2021-09-01 09:57:06 +00:00
|
|
|
});
|
2021-07-11 09:38:03 +00:00
|
|
|
|
2021-09-01 08:37:46 +00:00
|
|
|
let user = dsl::user_table
|
|
|
|
.filter(user_table::id.eq(&session.user_id))
|
|
|
|
.first::<UserTable>(&*(self.get_db_connection()?))?;
|
|
|
|
|
2021-07-11 07:33:19 +00:00
|
|
|
Ok(UserDetail::from(user))
|
|
|
|
}
|
2021-07-10 08:27:20 +00:00
|
|
|
|
2021-08-29 14:00:42 +00:00
|
|
|
pub fn user_dir(&self) -> Result<String, UserError> {
|
2021-09-01 03:21:42 +00:00
|
|
|
let session = self.get_session()?;
|
|
|
|
Ok(format!("{}/{}", self.config.root_dir, session.user_id))
|
2021-07-23 09:30:33 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 08:08:32 +00:00
|
|
|
pub fn user_id(&self) -> Result<String, UserError> { Ok(self.get_session()?.user_id) }
|
|
|
|
|
|
|
|
// pub fn user_token(&self) -> Result<String, UserError> {
|
|
|
|
// let user_detail = self.user_detail()?;
|
|
|
|
// Ok(user_detail.token)
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession {
|
|
|
|
async fn save_user(&self, user: UserTable) -> Result<UserTable, UserError> {
|
|
|
|
let conn = self.get_db_connection()?;
|
|
|
|
let _ = diesel::insert_into(user_table::table)
|
|
|
|
.values(user.clone())
|
|
|
|
.execute(&*conn)?;
|
|
|
|
|
|
|
|
Ok(user)
|
|
|
|
}
|
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
fn set_session(&self, session: Option<Session>) -> Result<(), UserError> {
|
|
|
|
log::trace!("Update user session: {:?}", session);
|
|
|
|
match &session {
|
|
|
|
None => KVStore::set_str(SESSION_CACHE_KEY, "".to_string()),
|
|
|
|
Some(session) => KVStore::set_str(SESSION_CACHE_KEY, session.clone().into()),
|
|
|
|
}
|
2021-07-18 15:56:36 +00:00
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
let mut write_guard = self.session.write();
|
|
|
|
*write_guard = session;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
fn get_session(&self) -> Result<Session, UserError> {
|
|
|
|
let mut session = {
|
|
|
|
let read_guard = self.session.read();
|
2021-07-19 08:15:20 +00:00
|
|
|
(*read_guard).clone()
|
|
|
|
};
|
2021-07-18 15:56:36 +00:00
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
if session.is_none() {
|
|
|
|
match KVStore::get_str(SESSION_CACHE_KEY) {
|
|
|
|
None => {},
|
|
|
|
Some(s) => {
|
|
|
|
session = Some(Session::from(s));
|
|
|
|
let _ = self.set_session(session.clone())?;
|
|
|
|
},
|
|
|
|
}
|
2021-07-18 15:56:36 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 03:21:42 +00:00
|
|
|
match session {
|
2021-08-30 14:44:17 +00:00
|
|
|
None => Err(ErrorBuilder::new(ErrorCode::UserNotLoginYet).build()),
|
2021-09-01 03:21:42 +00:00
|
|
|
Some(session) => Ok(session),
|
2021-07-18 15:56:36 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-31 15:01:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn update_user(
|
2021-09-01 08:37:46 +00:00
|
|
|
_server: Server,
|
2021-08-31 15:01:46 +00:00
|
|
|
pool: Arc<ConnectionPool>,
|
|
|
|
params: UpdateUserParams,
|
|
|
|
) -> Result<(), UserError> {
|
|
|
|
let changeset = UserTableChangeset::new(params);
|
|
|
|
let conn = pool.get()?;
|
|
|
|
diesel_update_table!(user_table, changeset, conn);
|
|
|
|
Ok(())
|
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-09-01 03:21:42 +00:00
|
|
|
match KVStore::get_str(SESSION_CACHE_KEY) {
|
2021-08-30 14:44:17 +00:00
|
|
|
None => Err(ErrorBuilder::new(ErrorCode::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-09-01 03:21:42 +00:00
|
|
|
const SESSION_CACHE_KEY: &str = "session_cache_key";
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
|
|
struct Session {
|
|
|
|
user_id: String,
|
|
|
|
token: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Session {
|
|
|
|
pub fn new(user_id: &str, token: &str) -> Self {
|
|
|
|
Self {
|
|
|
|
user_id: user_id.to_owned(),
|
|
|
|
token: token.to_owned(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::convert::From<String> for Session {
|
|
|
|
fn from(s: String) -> Self {
|
|
|
|
match serde_json::from_str(&s) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
2021-09-01 08:08:32 +00:00
|
|
|
log::error!("Deserialize string to Session failed: {:?}", e);
|
2021-09-01 03:21:42 +00:00
|
|
|
Session::default()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::convert::Into<String> for Session {
|
|
|
|
fn into(self) -> String {
|
|
|
|
match serde_json::to_string(&self) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
2021-09-01 08:08:32 +00:00
|
|
|
log::error!("Serialize session to string failed: {:?}", e);
|
2021-09-01 03:21:42 +00:00
|
|
|
"".to_string()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|