AppFlowy/rust-lib/flowy-user/src/services/user/user_session.rs

212 lines
6.2 KiB
Rust
Raw Normal View History

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-08-31 15:01:46 +00:00
services::user::{construct_user_server, database::UserDB, UserServerAPI},
sql_tables::{UserTable, UserTableChangeset},
};
2021-08-29 14:00:42 +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-08-29 14:00:42 +00:00
2021-08-31 15:01:46 +00:00
use crate::entities::UserToken;
use flowy_infra::kv::KVStore;
2021-08-31 15:01:46 +00:00
use flowy_sqlite::ConnectionPool;
2021-07-14 15:00:58 +00:00
use std::sync::{Arc, RwLock};
pub struct UserSessionConfig {
root_dir: String,
}
impl UserSessionConfig {
pub fn new(root_dir: &str) -> Self {
Self {
root_dir: root_dir.to_owned(),
}
}
}
2021-08-31 15:01:46 +00:00
type Server = Arc<dyn UserServerAPI + Send + Sync>;
pub struct UserSession {
database: UserDB,
config: UserSessionConfig,
#[allow(dead_code)]
2021-08-31 15:01:46 +00:00
pub(crate) server: Server,
user_id: RwLock<Option<String>>,
}
impl UserSession {
2021-08-31 15:01:46 +00:00
pub fn new(config: UserSessionConfig) -> Self {
let db = UserDB::new(&config.root_dir);
2021-08-31 15:01:46 +00:00
let server = construct_user_server();
Self {
database: db,
config,
2021-07-14 15:00:58 +00:00
server,
user_id: RwLock::new(None),
}
}
2021-07-16 15:18:12 +00:00
pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
2021-08-29 14:00:42 +00:00
let user_id = self.user_id()?;
2021-07-16 15:18:12 +00:00
self.database.get_connection(&user_id)
}
2021-08-31 15:01:46 +00:00
pub fn db_connection_pool(&self) -> Result<Arc<ConnectionPool>, UserError> {
let user_id = self.user_id()?;
self.database.get_pool(&user_id)
}
pub async fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError> {
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?;
Ok(user_table)
}
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError> {
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?;
Ok(user_table)
}
2021-08-31 09:25:08 +00:00
pub async fn sign_out(&self) -> Result<(), UserError> {
2021-08-31 15:01:46 +00:00
let user_detail = self.user_detail().await?;
2021-08-31 09:25:08 +00:00
match self.server.sign_out(&user_detail.token).await {
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 _ =
diesel::delete(dsl::user_table.filter(dsl::id.eq(&user_detail.id))).execute(&*conn)?;
let _ = self.server.sign_out(&user_detail.id);
let _ = self.database.close_user_db(&user_detail.id)?;
let _ = self.set_user_id(None)?;
2021-07-11 09:38:03 +00:00
Ok(())
}
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)
}
2021-08-31 15:01:46 +00:00
pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), UserError> {
let changeset = UserTableChangeset::new(params);
let conn = self.get_db_connection()?;
diesel_update_table!(user_table, changeset, conn);
2021-08-31 15:01:46 +00:00
Ok(())
}
2021-08-31 15:01:46 +00:00
pub async fn user_detail(&self) -> Result<UserDetail, UserError> {
2021-08-29 14:00:42 +00:00
let user_id = self.user_id()?;
let user = dsl::user_table
2021-07-11 09:38:03 +00:00
.filter(user_table::id.eq(&user_id))
.first::<UserTable>(&*(self.get_db_connection()?))?;
2021-08-31 15:01:46 +00:00
let server = self.server.clone();
let token = user.token.clone();
tokio::spawn(async move {
match server.get_user_detail(&token).await {
Ok(user_detail) => {
//
log::info!("{:?}", user_detail);
},
Err(e) => {
//
log::info!("{:?}", e);
},
}
})
.await;
2021-07-11 09:38:03 +00:00
Ok(UserDetail::from(user))
}
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-08-30 14:44:17 +00:00
Err(e) => Err(ErrorBuilder::new(ErrorCode::WriteCurrentIdFailed)
.error(e)
.build()),
}
}
2021-08-29 14:00:42 +00:00
pub fn user_dir(&self) -> Result<String, UserError> {
let user_id = self.user_id()?;
2021-07-23 09:30:33 +00:00
Ok(format!("{}/{}", self.config.root_dir, user_id))
}
2021-08-29 14:00:42 +00:00
pub fn user_id(&self) -> Result<String, UserError> {
let mut user_id = {
let read_guard = self.user_id.read().map_err(|e| {
2021-08-30 14:44:17 +00:00
ErrorBuilder::new(ErrorCode::ReadCurrentIdFailed)
.error(e)
.build()
})?;
(*read_guard).clone()
};
if user_id.is_none() {
user_id = KVStore::get_str(USER_ID_CACHE_KEY);
let _ = self.set_user_id(user_id.clone())?;
}
match user_id {
2021-08-30 14:44:17 +00:00
None => Err(ErrorBuilder::new(ErrorCode::UserNotLoginYet).build()),
Some(user_id) => Ok(user_id),
}
}
2021-08-31 09:25:08 +00:00
2021-08-31 15:01:46 +00:00
// pub fn user_token(&self) -> Result<String, UserError> {
// let user_detail = self.user_detail()?;
// Ok(user_detail.token)
// }
}
pub async fn update_user(
server: Server,
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> {
match KVStore::get_str(USER_ID_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))
}
}
const USER_ID_CACHE_KEY: &str = "user_id";