save user info to database after sign up

This commit is contained in:
appflowy 2021-07-10 16:27:20 +08:00
parent b9d7902acb
commit 55454c5bec
46 changed files with 458 additions and 277 deletions

View File

@ -18,6 +18,7 @@
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-user/tests" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-user/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-database/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" /> <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sqlite/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-infra/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.pub" /> <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/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" /> <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />

View File

@ -11,19 +11,24 @@ import 'package:protobuf/protobuf.dart' as $pb;
class User extends $pb.GeneratedMessage { class User extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'User', createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'User', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'email') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'password') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'email')
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'password')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
User._() : super(); User._() : super();
factory User({ factory User({
$core.String? id,
$core.String? name, $core.String? name,
$core.String? email, $core.String? email,
$core.String? password, $core.String? password,
}) { }) {
final _result = create(); final _result = create();
if (id != null) {
_result.id = id;
}
if (name != null) { if (name != null) {
_result.name = name; _result.name = name;
} }
@ -57,30 +62,39 @@ class User extends $pb.GeneratedMessage {
static User? _defaultInstance; static User? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.String get name => $_getSZ(0); $core.String get id => $_getSZ(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set name($core.String v) { $_setString(0, v); } set id($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasName() => $_has(0); $core.bool hasId() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearName() => clearField(1); void clearId() => clearField(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.String get email => $_getSZ(1); $core.String get name => $_getSZ(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set email($core.String v) { $_setString(1, v); } set name($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasEmail() => $_has(1); $core.bool hasName() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearEmail() => clearField(2); void clearName() => clearField(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.String get password => $_getSZ(2); $core.String get email => $_getSZ(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
set password($core.String v) { $_setString(2, v); } set email($core.String v) { $_setString(2, v); }
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.bool hasPassword() => $_has(2); $core.bool hasEmail() => $_has(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
void clearPassword() => clearField(3); void clearEmail() => clearField(3);
@$pb.TagNumber(4)
$core.String get password => $_getSZ(3);
@$pb.TagNumber(4)
set password($core.String v) { $_setString(3, v); }
@$pb.TagNumber(4)
$core.bool hasPassword() => $_has(3);
@$pb.TagNumber(4)
void clearPassword() => clearField(4);
} }

View File

@ -9,9 +9,10 @@ import 'dart:core' as $core;
const User$json = const { const User$json = const {
'1': 'User', '1': 'User',
'2': const [ '2': const [
const {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'}, const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'email', '3': 2, '4': 1, '5': 9, '10': 'email'}, const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
const {'1': 'password', '3': 3, '4': 1, '5': 9, '10': 'password'}, const {'1': 'email', '3': 3, '4': 1, '5': 9, '10': 'email'},
const {'1': 'password', '3': 4, '4': 1, '5': 9, '10': 'password'},
], ],
}; };

View File

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

View File

@ -36,8 +36,8 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into(); let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
log::trace!( log::trace!(
"[FFI]: {} Async Event: {:?} with {} port", "[FFI]: {} Async Event: {:?} with {} port",
&request.id(), &request.id,
&request.event(), &request.event,
port port
); );
@ -50,11 +50,7 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
#[no_mangle] #[no_mangle]
pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 { pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into(); let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
log::trace!( log::trace!("[FFI]: {} Sync Event: {:?}", &request.id, &request.event,);
"[FFI]: {} Sync Event: {:?}",
&request.id(),
&request.event(),
);
let _response = EventDispatch::sync_send(request); let _response = EventDispatch::sync_send(request);
// FFIResponse { } // FFIResponse { }

View File

@ -1,16 +0,0 @@
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)) }
}

View File

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

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
error::{InternalError, SystemError}, errors::{DispatchError, InternalError},
request::{unexpected_none_payload, EventRequest, FromRequest, Payload}, request::{unexpected_none_payload, EventRequest, FromRequest, Payload},
response::{EventResponse, Responder, ResponseBuilder, ToBytes}, response::{EventResponse, Responder, ResponseBuilder, ToBytes},
util::ready::{ready, Ready}, util::ready::{ready, Ready},
@ -53,8 +53,8 @@ impl<T> FromRequest for Data<T>
where where
T: FromBytes + 'static, T: FromBytes + 'static,
{ {
type Error = SystemError; type Error = DispatchError;
type Future = Ready<Result<Self, SystemError>>; type Future = Ready<Result<Self, DispatchError>>;
#[inline] #[inline]
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
@ -76,7 +76,7 @@ where
match self.into_inner().into_bytes() { match self.into_inner().into_bytes() {
Ok(bytes) => ResponseBuilder::Ok().data(bytes.to_vec()).build(), Ok(bytes) => ResponseBuilder::Ok().data(bytes.to_vec()).build(),
Err(e) => { Err(e) => {
let system_err: SystemError = InternalError::new(format!("{:?}", e)).into(); let system_err: DispatchError = InternalError::new(format!("{:?}", e)).into();
system_err.into() system_err.into()
}, },
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
error::{Error, InternalError, SystemError}, errors::{DispatchError, Error, InternalError},
module::{as_module_map, Module, ModuleMap, ModuleRequest}, module::{as_module_map, Module, ModuleMap, ModuleRequest},
response::EventResponse, response::EventResponse,
service::{Service, ServiceFactory}, service::{Service, ServiceFactory},
@ -129,7 +129,7 @@ pub(crate) struct DispatchService {
impl Service<DispatchContext> for DispatchService { impl Service<DispatchContext> for DispatchService {
type Response = EventResponse; type Response = EventResponse;
type Error = SystemError; type Error = DispatchError;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
#[cfg_attr( #[cfg_attr(

View File

@ -1,3 +0,0 @@
mod error;
pub use error::*;

View File

@ -8,45 +8,43 @@ use std::{fmt, option::NoneError};
use tokio::sync::mpsc::error::SendError; use tokio::sync::mpsc::error::SendError;
pub trait Error: fmt::Debug + fmt::Display + DynClone + Send + Sync { pub trait Error: fmt::Debug + fmt::Display + DynClone + Send + Sync {
fn status_code(&self) -> StatusCode; fn as_response(&self) -> EventResponse { EventResponse::new(StatusCode::Err) }
fn as_response(&self) -> EventResponse { EventResponse::new(self.status_code()) }
} }
dyn_clone::clone_trait_object!(Error); dyn_clone::clone_trait_object!(Error);
impl<T: Error + 'static> From<T> for SystemError { impl<T: Error + 'static> From<T> for DispatchError {
fn from(err: T) -> SystemError { fn from(err: T) -> DispatchError {
SystemError { DispatchError {
inner: Box::new(err), inner: Box::new(err),
} }
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct SystemError { pub struct DispatchError {
inner: Box<dyn Error>, inner: Box<dyn Error>,
} }
impl SystemError { impl DispatchError {
pub fn inner_error(&self) -> &dyn Error { self.inner.as_ref() } pub fn inner_error(&self) -> &dyn Error { self.inner.as_ref() }
} }
impl fmt::Display for SystemError { impl fmt::Display for DispatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) } fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) }
} }
impl fmt::Debug for SystemError { impl fmt::Debug for DispatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", &self.inner) } fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", &self.inner) }
} }
impl std::error::Error for SystemError { impl std::error::Error for DispatchError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
fn cause(&self) -> Option<&dyn std::error::Error> { None } fn cause(&self) -> Option<&dyn std::error::Error> { None }
} }
impl From<SendError<EventRequest>> for SystemError { impl From<SendError<EventRequest>> for DispatchError {
fn from(err: SendError<EventRequest>) -> Self { fn from(err: SendError<EventRequest>) -> Self {
InternalError { InternalError {
inner: format!("{}", err), inner: format!("{}", err),
@ -55,7 +53,7 @@ impl From<SendError<EventRequest>> for SystemError {
} }
} }
impl From<NoneError> for SystemError { impl From<NoneError> for DispatchError {
fn from(s: NoneError) -> Self { fn from(s: NoneError) -> Self {
InternalError { InternalError {
inner: format!("Unexpected none: {:?}", s), inner: format!("Unexpected none: {:?}", s),
@ -64,16 +62,16 @@ impl From<NoneError> for SystemError {
} }
} }
impl From<String> for SystemError { impl From<String> for DispatchError {
fn from(s: String) -> Self { InternalError { inner: s }.into() } fn from(s: String) -> Self { InternalError { inner: s }.into() }
} }
impl From<SystemError> for EventResponse { impl From<DispatchError> for EventResponse {
fn from(err: SystemError) -> Self { err.inner_error().as_response() } fn from(err: DispatchError) -> Self { err.inner_error().as_response() }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct InternalError<T: Clone> { pub(crate) struct InternalError<T: Clone> {
inner: T, inner: T,
} }
@ -99,8 +97,6 @@ impl<T> Error for InternalError<T>
where where
T: fmt::Debug + fmt::Display + 'static + Clone + Send + Sync, T: fmt::Debug + fmt::Display + 'static + Clone + Send + Sync,
{ {
fn status_code(&self) -> StatusCode { StatusCode::Err }
fn as_response(&self) -> EventResponse { fn as_response(&self) -> EventResponse {
let error = InternalError { let error = InternalError {
inner: format!("{}", self.inner), inner: format!("{}", self.inner),
@ -111,7 +107,7 @@ where
} }
} }
impl Serialize for SystemError { impl Serialize for DispatchError {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where where
S: Serializer, S: Serializer,

View File

@ -0,0 +1,3 @@
mod errors;
pub use errors::*;

View File

@ -1,6 +1,6 @@
#![feature(try_trait)] #![feature(try_trait)]
mod error; mod errors;
mod module; mod module;
mod request; mod request;
mod response; mod response;
@ -11,6 +11,8 @@ mod data;
mod dispatch; mod dispatch;
mod system; mod system;
pub use errors::Error;
pub mod prelude { pub mod prelude {
pub use crate::{data::*, dispatch::*, error::*, module::*, request::*, response::*}; pub use crate::{data::*, dispatch::*, errors::*, module::*, request::*, response::*};
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
error::{InternalError, SystemError}, errors::{DispatchError, InternalError},
request::{payload::Payload, EventRequest, FromRequest}, request::{payload::Payload, EventRequest, FromRequest},
util::ready::{ready, Ready}, util::ready::{ready, Ready},
}; };
@ -43,15 +43,18 @@ impl<T> FromRequest for ModuleData<T>
where where
T: ?Sized + Send + Sync + 'static, T: ?Sized + Send + Sync + 'static,
{ {
type Error = SystemError; type Error = DispatchError;
type Future = Ready<Result<Self, SystemError>>; type Future = Ready<Result<Self, DispatchError>>;
#[inline] #[inline]
fn from_request(req: &EventRequest, _: &mut Payload) -> Self::Future { fn from_request(req: &EventRequest, _: &mut Payload) -> Self::Future {
if let Some(data) = req.module_data::<ModuleData<T>>() { if let Some(data) = req.module_data::<ModuleData<T>>() {
ready(Ok(data.clone())) ready(Ok(data.clone()))
} else { } else {
let msg = format!("Failed to get the module data(type: {})", type_name::<T>()); let msg = format!(
"Failed to get the module data of type: {}",
type_name::<T>()
);
log::error!("{}", msg,); log::error!("{}", msg,);
ready(Err(InternalError::new(msg).into())) ready(Err(InternalError::new(msg).into()))
} }

View File

@ -12,7 +12,7 @@ use futures_core::ready;
use pin_project::pin_project; use pin_project::pin_project;
use crate::{ use crate::{
error::{InternalError, SystemError}, errors::{DispatchError, InternalError},
module::{container::ModuleDataMap, ModuleData}, module::{container::ModuleDataMap, ModuleData},
request::{payload::Payload, EventRequest, FromRequest}, request::{payload::Payload, EventRequest, FromRequest},
response::{EventResponse, Responder}, response::{EventResponse, Responder},
@ -51,7 +51,8 @@ impl<T: Display + Eq + Hash + Debug + Clone> std::convert::From<T> for Event {
fn from(t: T) -> Self { Event(format!("{}", t)) } fn from(t: T) -> Self { Event(format!("{}", t)) }
} }
pub type EventServiceFactory = BoxServiceFactory<(), ServiceRequest, ServiceResponse, SystemError>; pub type EventServiceFactory =
BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>;
pub struct Module { pub struct Module {
pub name: String, pub name: String,
@ -111,8 +112,8 @@ impl Module {
#[derive(Debug)] #[derive(Debug)]
pub struct ModuleRequest { pub struct ModuleRequest {
pub(crate) id: String, pub id: String,
pub(crate) event: Event, pub event: Event,
pub(crate) payload: Payload, pub(crate) payload: Payload,
} }
@ -145,7 +146,7 @@ impl std::fmt::Display for ModuleRequest {
impl ServiceFactory<ModuleRequest> for Module { impl ServiceFactory<ModuleRequest> for Module {
type Response = EventResponse; type Response = EventResponse;
type Error = SystemError; type Error = DispatchError;
type Service = BoxService<ModuleRequest, Self::Response, Self::Error>; type Service = BoxService<ModuleRequest, Self::Response, Self::Error>;
type Context = (); type Context = ();
type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>; type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>;
@ -171,7 +172,7 @@ pub struct ModuleService {
impl Service<ModuleRequest> for ModuleService { impl Service<ModuleRequest> for ModuleService {
type Response = EventResponse; type Response = EventResponse;
type Error = SystemError; type Error = DispatchError;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn call(&self, request: ModuleRequest) -> Self::Future { fn call(&self, request: ModuleRequest) -> Self::Future {
@ -196,17 +197,14 @@ impl Service<ModuleRequest> for ModuleService {
} }
} }
// type BoxModuleService = BoxService<ServiceRequest, ServiceResponse,
// SystemError>;
#[pin_project] #[pin_project]
pub struct ModuleServiceFuture { pub struct ModuleServiceFuture {
#[pin] #[pin]
fut: BoxFuture<'static, Result<ServiceResponse, SystemError>>, fut: BoxFuture<'static, Result<ServiceResponse, DispatchError>>,
} }
impl Future for ModuleServiceFuture { impl Future for ModuleServiceFuture {
type Output = Result<EventResponse, SystemError>; type Output = Result<EventResponse, DispatchError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop { loop {

View File

@ -1,7 +1,7 @@
use std::future::Future; use std::future::Future;
use crate::{ use crate::{
error::{InternalError, SystemError}, errors::{DispatchError, InternalError},
module::{Event, ModuleDataMap}, module::{Event, ModuleDataMap},
request::payload::Payload, request::payload::Payload,
util::ready::{ready, Ready}, util::ready::{ready, Ready},
@ -48,7 +48,7 @@ impl EventRequest {
} }
pub trait FromRequest: Sized { pub trait FromRequest: Sized {
type Error: Into<SystemError>; type Error: Into<DispatchError>;
type Future: Future<Output = Result<Self, Self::Error>>; type Future: Future<Output = Result<Self, Self::Error>>;
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future; fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future;
@ -56,15 +56,15 @@ pub trait FromRequest: Sized {
#[doc(hidden)] #[doc(hidden)]
impl FromRequest for () { impl FromRequest for () {
type Error = SystemError; type Error = DispatchError;
type Future = Ready<Result<(), SystemError>>; type Future = Ready<Result<(), DispatchError>>;
fn from_request(_req: &EventRequest, _payload: &mut Payload) -> Self::Future { ready(Ok(())) } fn from_request(_req: &EventRequest, _payload: &mut Payload) -> Self::Future { ready(Ok(())) }
} }
#[doc(hidden)] #[doc(hidden)]
impl FromRequest for String { impl FromRequest for String {
type Error = SystemError; type Error = DispatchError;
type Future = Ready<Result<Self, Self::Error>>; type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
@ -75,7 +75,7 @@ impl FromRequest for String {
} }
} }
pub fn unexpected_none_payload(request: &EventRequest) -> SystemError { pub fn unexpected_none_payload(request: &EventRequest) -> DispatchError {
log::warn!("{:?} expected payload", &request.event); log::warn!("{:?} expected payload", &request.event);
InternalError::new("Expected payload").into() InternalError::new("Expected payload").into()
} }
@ -85,7 +85,7 @@ impl<T> FromRequest for Result<T, T::Error>
where where
T: FromRequest, T: FromRequest,
{ {
type Error = SystemError; type Error = DispatchError;
type Future = FromRequestFuture<T::Future>; type Future = FromRequestFuture<T::Future>;
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
@ -105,7 +105,7 @@ impl<Fut, T, E> Future for FromRequestFuture<Fut>
where where
Fut: Future<Output = Result<T, E>>, Fut: Future<Output = Result<T, E>>,
{ {
type Output = Result<Result<T, E>, SystemError>; type Output = Result<Result<T, E>, DispatchError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
error::SystemError, errors::DispatchError,
request::Payload, request::Payload,
response::{EventResponse, StatusCode}, response::{EventResponse, StatusCode},
}; };
@ -14,7 +14,7 @@ macro_rules! static_response {
pub struct ResponseBuilder<T = Payload> { pub struct ResponseBuilder<T = Payload> {
pub payload: T, pub payload: T,
pub status: StatusCode, pub status: StatusCode,
pub error: Option<SystemError>, pub error: Option<DispatchError>,
} }
impl ResponseBuilder { impl ResponseBuilder {
@ -31,7 +31,7 @@ impl ResponseBuilder {
self self
} }
pub fn error(mut self, error: SystemError) -> Self { pub fn error(mut self, error: DispatchError) -> Self {
self.error = Some(error); self.error = Some(error);
self self
} }

View File

@ -1,5 +1,5 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::error::{InternalError, SystemError}; use crate::errors::{DispatchError, InternalError};
use crate::{ use crate::{
request::EventRequest, request::EventRequest,
response::{EventResponse, ResponseBuilder}, response::{EventResponse, ResponseBuilder},
@ -28,7 +28,7 @@ impl_responder!(Bytes);
impl<T, E> Responder for Result<T, E> impl<T, E> Responder for Result<T, E>
where where
T: Responder, T: Responder,
E: Into<SystemError>, E: Into<DispatchError>,
{ {
fn respond_to(self, request: &EventRequest) -> EventResponse { fn respond_to(self, request: &EventRequest) -> EventResponse {
match self { match self {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
data::Data, data::Data,
error::SystemError, errors::DispatchError,
request::{EventRequest, Payload}, request::{EventRequest, Payload},
response::Responder, response::Responder,
}; };
@ -19,7 +19,7 @@ pub struct EventResponse {
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
pub payload: Payload, pub payload: Payload,
pub status_code: StatusCode, pub status_code: StatusCode,
pub error: Option<SystemError>, pub error: Option<DispatchError>,
} }
impl EventResponse { impl EventResponse {
@ -58,7 +58,7 @@ pub type ResponseResult<T, E> = std::result::Result<Data<T>, E>;
pub fn response_ok<T, E>(data: T) -> Result<Data<T>, E> pub fn response_ok<T, E>(data: T) -> Result<Data<T>, E>
where where
E: Into<SystemError>, E: Into<DispatchError>,
{ {
Ok(Data(data)) Ok(Data(data))
} }

View File

@ -9,7 +9,7 @@ use futures_core::ready;
use pin_project::pin_project; use pin_project::pin_project;
use crate::{ use crate::{
error::SystemError, errors::DispatchError,
request::{payload::Payload, EventRequest, FromRequest}, request::{payload::Payload, EventRequest, FromRequest},
response::{EventResponse, Responder}, response::{EventResponse, Responder},
service::{Service, ServiceFactory, ServiceRequest, ServiceResponse}, service::{Service, ServiceFactory, ServiceRequest, ServiceResponse},
@ -73,7 +73,7 @@ where
R::Output: Responder, R::Output: Responder,
{ {
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = SystemError; type Error = DispatchError;
type Service = Self; type Service = Self;
type Context = (); type Context = ();
type Future = Ready<Result<Self::Service, Self::Error>>; type Future = Ready<Result<Self::Service, Self::Error>>;
@ -89,7 +89,7 @@ where
R::Output: Responder, R::Output: Responder,
{ {
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = SystemError; type Error = DispatchError;
type Future = HandlerServiceFuture<H, T, R>; type Future = HandlerServiceFuture<H, T, R>;
fn call(&self, req: ServiceRequest) -> Self::Future { fn call(&self, req: ServiceRequest) -> Self::Future {
@ -118,7 +118,7 @@ where
R: Future + Sync + Send, R: Future + Sync + Send,
R::Output: Responder, R::Output: Responder,
{ {
type Output = Result<ServiceResponse, SystemError>; type Output = Result<ServiceResponse, DispatchError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop { loop {
@ -132,7 +132,7 @@ where
}, },
Err(err) => { Err(err) => {
let req = req.take().unwrap(); let req = req.take().unwrap();
let system_err: SystemError = err.into(); let system_err: DispatchError = err.into();
let res: EventResponse = system_err.into(); let res: EventResponse = system_err.into();
return Poll::Ready(Ok(ServiceResponse::new(req, res))); return Poll::Ready(Ok(ServiceResponse::new(req, res)));
}, },
@ -175,7 +175,7 @@ macro_rules! tuple_from_req ({$tuple_type:ident, $(($n:tt, $T:ident)),+} => {
#[allow(unused_parens)] #[allow(unused_parens)]
impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+) impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+)
{ {
type Error = SystemError; type Error = DispatchError;
type Future = $tuple_type<$($T),+>; type Future = $tuple_type<$($T),+>;
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
@ -196,7 +196,7 @@ macro_rules! tuple_from_req ({$tuple_type:ident, $(($n:tt, $T:ident)),+} => {
impl<$($T: FromRequest),+> Future for $tuple_type<$($T),+> impl<$($T: FromRequest),+> Future for $tuple_type<$($T),+>
{ {
type Output = Result<($($T,)+), SystemError>; type Output = Result<($($T,)+), DispatchError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project(); let mut this = self.project();

View File

@ -0,0 +1,9 @@
[package]
name = "flowy-infra"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
uuid = { version = "0.8", features = ["serde", "v4"] }

View File

@ -0,0 +1 @@
pub fn uuid() -> String { uuid::Uuid::new_v4().to_string() }

View File

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

View File

@ -4,16 +4,21 @@ use crate::{
}; };
use r2d2::PooledConnection; use r2d2::PooledConnection;
pub struct DataBase { pub struct Database {
uri: String, uri: String,
pool: ConnectionPool, pool: ConnectionPool,
} }
pub type DBConnection = PooledConnection<ConnectionManager>; pub type DBConnection = PooledConnection<ConnectionManager>;
impl DataBase { impl Database {
pub fn new(dir: &str, name: &str, pool_config: PoolConfig) -> Result<Self> { pub fn new(dir: &str, name: &str, pool_config: PoolConfig) -> Result<Self> {
let uri = db_file_uri(dir, name); let uri = db_file_uri(dir, name);
if !std::path::PathBuf::from(dir).exists() {
log::error!("Create database failed. {} not exists", &dir);
}
let pool = ConnectionPool::new(pool_config, &uri)?; let pool = ConnectionPool::new(pool_config, &uri)?;
Ok(Self { uri, pool }) Ok(Self { uri, pool })
} }

View File

@ -115,12 +115,7 @@ impl ManageConnection for ConnectionManager {
type Connection = SqliteConnection; type Connection = SqliteConnection;
type Error = crate::Error; type Error = crate::Error;
fn connect(&self) -> Result<Self::Connection> { fn connect(&self) -> Result<Self::Connection> { Ok(SqliteConnection::establish(&self.db_uri)?) }
if !std::path::PathBuf::from(&self.db_uri).exists() {
log::error!("db file not exists");
}
Ok(SqliteConnection::establish(&self.db_uri)?)
}
fn is_valid(&self, conn: &mut Self::Connection) -> Result<()> { fn is_valid(&self, conn: &mut Self::Connection) -> Result<()> {
Ok(conn.execute("SELECT 1").map(|_| ())?) Ok(conn.execute("SELECT 1").map(|_| ())?)

View File

@ -12,6 +12,7 @@ flowy-log = { path = "../flowy-log" }
flowy-derive = { path = "../flowy-derive" } flowy-derive = { path = "../flowy-derive" }
flowy-database = { path = "../flowy-database" } flowy-database = { path = "../flowy-database" }
flowy-sqlite = { path = "../flowy-sqlite" } flowy-sqlite = { path = "../flowy-sqlite" }
flowy-infra = { path = "../flowy-infra" }
tracing = { version = "0.1", features = ["log"] } tracing = { version = "0.1", features = ["log"] }
bytes = "1.0" bytes = "1.0"
@ -23,6 +24,8 @@ log = "0.4.14"
protobuf = {version = "2.18.0"} protobuf = {version = "2.18.0"}
lazy_static = "1.4.0" lazy_static = "1.4.0"
fancy-regex = "0.5.0" fancy-regex = "0.5.0"
diesel = {version = "1.4.7", features = ["sqlite"]}
diesel_derives = {version = "1.4.1", features = ["sqlite"]}
[dev-dependencies] [dev-dependencies]
quickcheck = "0.9.2" quickcheck = "0.9.2"

View File

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

View File

@ -0,0 +1,3 @@
mod user_table;
pub use user_table::*;

View File

@ -0,0 +1,30 @@
use crate::domain::{UserEmail, UserName, UserPassword};
use flowy_database::schema::user_table;
use flowy_derive::ProtoBuf;
#[derive(ProtoBuf, Clone, Default, Queryable, Identifiable, Insertable)]
#[table_name = "user_table"]
pub struct User {
#[pb(index = 1)]
pub(crate) id: String,
#[pb(index = 2)]
name: String,
#[pb(index = 3)]
email: String,
#[pb(index = 4)]
password: String,
}
impl User {
pub fn new(id: String, name: String, email: String, password: String) -> Self {
Self {
id,
name,
email,
password,
}
}
}

View File

@ -1,13 +1,11 @@
mod sign_in; mod sign_in;
mod sign_up; mod sign_up;
mod user;
mod user_email; mod user_email;
mod user_name; mod user_name;
mod user_password; mod user_password;
pub use sign_in::*; pub use sign_in::*;
pub use sign_up::*; pub use sign_up::*;
pub use user::*;
pub use user_email::*; pub use user_email::*;
pub use user_name::*; pub use user_name::*;
pub use user_password::*; pub use user_password::*;

View File

@ -1,24 +0,0 @@
use crate::domain::{UserEmail, UserName, UserPassword};
use flowy_derive::ProtoBuf;
#[derive(ProtoBuf, Default)]
pub struct User {
#[pb(index = 1)]
name: String,
#[pb(index = 2)]
email: String,
#[pb(index = 3)]
password: String,
}
impl User {
pub fn new(name: UserName, email: UserEmail, password: UserPassword) -> Self {
Self {
name: name.0,
email: email.0,
password: password.0,
}
}
}

View File

@ -1,48 +0,0 @@
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),
}
}
}

View File

@ -1,23 +1,34 @@
use flowy_database::DataBaseError; use derive_more::Display;
use std::sync::PoisonError; use flowy_dispatch::prelude::{DispatchError, EventResponse, ResponseBuilder, StatusCode};
use std::{io, sync::PoisonError};
#[derive(Debug)] #[derive(Debug, Clone, Display)]
pub enum UserError { pub enum UserError {
DBInit(String), #[display(fmt = "User db error:{}", _0)]
DBNotInit, Database(String),
UserNotLogin, #[display(fmt = "User auth error:{}", _0)]
DBConnection(String), Auth(String),
#[display(fmt = "User sync error: {}", _0)]
PoisonError(String), PoisonError(String),
} }
impl std::convert::From<DataBaseError> for UserError { impl std::convert::From<flowy_database::result::Error> for UserError {
fn from(error: DataBaseError) -> Self { UserError::DBInit(format!("{:?}", error)) } fn from(error: flowy_database::result::Error) -> Self {
} UserError::Database(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 { impl std::convert::From<flowy_sqlite::Error> for UserError {
fn from(e: flowy_sqlite::Error) -> Self { UserError::DBConnection(format!("{:?}", e)) } fn from(e: flowy_sqlite::Error) -> Self { UserError::Database(format!("{:?}", e)) }
}
impl std::convert::From<UserError> for String {
fn from(e: UserError) -> Self { format!("{:?}", e) }
}
impl std::convert::Into<DispatchError> for UserError {
fn into(self) -> DispatchError {
let user_error: String = self.into();
user_error.into()
}
} }

View File

@ -1,4 +1,4 @@
use crate::domain::{user::*, user_session::UserSession}; use crate::{domain::user::*, services::user_session::UserSession};
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
use std::{convert::TryInto, sync::Arc}; use std::{convert::TryInto, sync::Arc};
@ -21,16 +21,19 @@ pub async fn user_sign_in(data: Data<SignInRequest>) -> ResponseResult<SignInRes
name = "user_sign_up", name = "user_sign_up",
skip(data, session), skip(data, session),
fields( fields(
email = %data.email, email = %data.email,
name = %data.name,
) )
)] )]
pub async fn user_sign_up( pub async fn user_sign_up(
data: Data<SignUpRequest>, data: Data<SignUpRequest>,
session: ModuleData<Arc<UserSession>>, session: ModuleData<Arc<UserSession>>,
) -> ResponseResult<SignUpResponse, String> { ) -> ResponseResult<SignUpResponse, String> {
let _params: SignUpParams = data.into_inner().try_into()?; let params: SignUpParams = data.into_inner().try_into()?;
// TODO: user sign up // TODO: user sign up
let _user = session.sign_up(params)?;
let fake_resp = SignUpResponse::new(true); let fake_resp = SignUpResponse::new(true);
response_ok(fake_resp) response_ok(fake_resp)
} }

View File

@ -4,7 +4,11 @@ pub mod event;
mod handlers; mod handlers;
pub mod module; pub mod module;
mod protobuf; mod protobuf;
mod services;
#[macro_use]
extern crate flowy_database;
pub mod prelude { pub mod prelude {
pub use crate::{domain::*, handlers::auth::*}; pub use crate::{domain::*, handlers::auth::*, services::user_session::*};
} }

View File

@ -1,10 +1,6 @@
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
use crate::{ use crate::{event::UserEvent, handlers::*, services::user_session::UserSession};
domain::{user_db::*, user_session::UserSession},
event::UserEvent,
handlers::*,
};
use std::sync::Arc; use std::sync::Arc;
pub fn create(user_session: Arc<UserSession>) -> Module { pub fn create(user_session: Arc<UserSession>) -> Module {

View File

@ -26,6 +26,7 @@
#[derive(PartialEq,Clone,Default)] #[derive(PartialEq,Clone,Default)]
pub struct User { pub struct User {
// message fields // message fields
pub id: ::std::string::String,
pub name: ::std::string::String, pub name: ::std::string::String,
pub email: ::std::string::String, pub email: ::std::string::String,
pub password: ::std::string::String, pub password: ::std::string::String,
@ -45,7 +46,33 @@ impl User {
::std::default::Default::default() ::std::default::Default::default()
} }
// string name = 1; // string id = 1;
pub fn get_id(&self) -> &str {
&self.id
}
pub fn clear_id(&mut self) {
self.id.clear();
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: ::std::string::String) {
self.id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_id(&mut self) -> &mut ::std::string::String {
&mut self.id
}
// Take field
pub fn take_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// string name = 2;
pub fn get_name(&self) -> &str { pub fn get_name(&self) -> &str {
@ -71,7 +98,7 @@ impl User {
::std::mem::replace(&mut self.name, ::std::string::String::new()) ::std::mem::replace(&mut self.name, ::std::string::String::new())
} }
// string email = 2; // string email = 3;
pub fn get_email(&self) -> &str { pub fn get_email(&self) -> &str {
@ -97,7 +124,7 @@ impl User {
::std::mem::replace(&mut self.email, ::std::string::String::new()) ::std::mem::replace(&mut self.email, ::std::string::String::new())
} }
// string password = 3; // string password = 4;
pub fn get_password(&self) -> &str { pub fn get_password(&self) -> &str {
@ -134,12 +161,15 @@ impl ::protobuf::Message for User {
let (field_number, wire_type) = is.read_tag_unpack()?; let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number { match field_number {
1 => { 1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
}, },
2 => { 2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.email)?; ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
}, },
3 => { 3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.email)?;
},
4 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.password)?; ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.password)?;
}, },
_ => { _ => {
@ -154,14 +184,17 @@ impl ::protobuf::Message for User {
#[allow(unused_variables)] #[allow(unused_variables)]
fn compute_size(&self) -> u32 { fn compute_size(&self) -> u32 {
let mut my_size = 0; let mut my_size = 0;
if !self.id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.name.is_empty() { if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.name); my_size += ::protobuf::rt::string_size(2, &self.name);
} }
if !self.email.is_empty() { if !self.email.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.email); my_size += ::protobuf::rt::string_size(3, &self.email);
} }
if !self.password.is_empty() { if !self.password.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.password); my_size += ::protobuf::rt::string_size(4, &self.password);
} }
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size); self.cached_size.set(my_size);
@ -169,14 +202,17 @@ impl ::protobuf::Message for User {
} }
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.id.is_empty() {
os.write_string(1, &self.id)?;
}
if !self.name.is_empty() { if !self.name.is_empty() {
os.write_string(1, &self.name)?; os.write_string(2, &self.name)?;
} }
if !self.email.is_empty() { if !self.email.is_empty() {
os.write_string(2, &self.email)?; os.write_string(3, &self.email)?;
} }
if !self.password.is_empty() { if !self.password.is_empty() {
os.write_string(3, &self.password)?; os.write_string(4, &self.password)?;
} }
os.write_unknown_fields(self.get_unknown_fields())?; os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
@ -216,6 +252,11 @@ impl ::protobuf::Message for User {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| { descriptor.get(|| {
let mut fields = ::std::vec::Vec::new(); let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"id",
|m: &User| { &m.id },
|m: &mut User| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"name", "name",
|m: &User| { &m.name }, |m: &User| { &m.name },
@ -247,6 +288,7 @@ impl ::protobuf::Message for User {
impl ::protobuf::Clear for User { impl ::protobuf::Clear for User {
fn clear(&mut self) { fn clear(&mut self) {
self.id.clear();
self.name.clear(); self.name.clear();
self.email.clear(); self.email.clear();
self.password.clear(); self.password.clear();
@ -267,19 +309,23 @@ impl ::protobuf::reflect::ProtobufValue for User {
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\nuser.proto\"L\n\x04User\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04nam\ \n\nuser.proto\"\\\n\x04User\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\
e\x12\x14\n\x05email\x18\x02\x20\x01(\tR\x05email\x12\x1a\n\x08password\ \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x14\n\x05email\x18\
\x18\x03\x20\x01(\tR\x08passwordJ\xcf\x01\n\x06\x12\x04\0\0\x06\x01\n\ \x03\x20\x01(\tR\x05email\x12\x1a\n\x08password\x18\x04\x20\x01(\tR\x08p\
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\ asswordJ\x86\x02\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\0\
\n\x03\x04\0\x01\x12\x03\x02\x08\x0c\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\ \x12\n\n\n\x02\x04\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x04\0\x01\x12\x03\
\x04\x14\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\ \x02\x08\x0c\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\
\x02\0\x01\x12\x03\x03\x0b\x0f\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ \0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\
\x12\x13\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\ \x0b\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\
\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\ \x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\
\x0b\x10\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\ \x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\
\x04\0\x02\x02\x12\x03\x05\x04\x18\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\ \0\x02\x01\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\
\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x13\n\x0c\n\x05\ \x04\x15\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\
\x04\0\x02\x02\x03\x12\x03\x05\x16\x17b\x06proto3\ \0\x02\x02\x01\x12\x03\x05\x0b\x10\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\
\x05\x13\x14\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x18\n\x0c\n\x05\
\x04\0\x02\x03\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\
\x03\x06\x0b\x13\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x16\x17b\x06p\
roto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,7 +1,8 @@
syntax = "proto3"; syntax = "proto3";
message User { message User {
string name = 1; string id = 1;
string email = 2; string name = 2;
string password = 3; string email = 3;
string password = 4;
} }

View File

@ -1,5 +1,5 @@
use crate::errors::UserError; use crate::errors::UserError;
use flowy_database::{DBConnection, DataBase}; use flowy_database::{DBConnection, Database};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::{ use std::{
cell::RefCell, cell::RefCell,
@ -22,7 +22,7 @@ fn get_user_id() -> Option<String> { USER_ID.with(|id| id.borrow().clone()) }
static IS_USER_DB_INIT: AtomicBool = AtomicBool::new(false); static IS_USER_DB_INIT: AtomicBool = AtomicBool::new(false);
lazy_static! { lazy_static! {
static ref USER_DB_INNER: RwLock<Option<DataBase>> = RwLock::new(None); static ref DB: RwLock<Option<Database>> = RwLock::new(None);
} }
pub(crate) struct UserDB { pub(crate) struct UserDB {
@ -37,17 +37,23 @@ impl UserDB {
} }
fn open_user_db(&self, user_id: &str) -> Result<(), UserError> { fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
let user_dir = format!("{}/{}", self.db_dir, user_id); let dir = format!("{}/{}", self.db_dir, user_id);
let database = flowy_database::init(&user_dir)?; let db = flowy_database::init(&dir).map_err(|e| UserError::Database(format!("{:?}", e)))?;
let mut write_guard = USER_DB_INNER.write()?;
let mut user_db = DB
.write()
.map_err(|e| UserError::Database(format!("Open user db failed. {:?}", e)))?;
*(user_db) = Some(db);
set_user_id(Some(user_id.to_owned())); set_user_id(Some(user_id.to_owned()));
*(write_guard) = Some(database);
IS_USER_DB_INIT.store(true, Ordering::SeqCst); IS_USER_DB_INIT.store(true, Ordering::SeqCst);
Ok(()) Ok(())
} }
pub(crate) fn close_user_db(&mut self) -> Result<(), UserError> { pub(crate) fn close_user_db(&mut self) -> Result<(), UserError> {
let mut write_guard = USER_DB_INNER.write()?; let mut write_guard = DB
.write()
.map_err(|e| UserError::Database(format!("Close user db failed. {:?}", e)))?;
*write_guard = None; *write_guard = None;
set_user_id(None); set_user_id(None);
IS_USER_DB_INIT.store(false, Ordering::SeqCst); IS_USER_DB_INIT.store(false, Ordering::SeqCst);
@ -62,16 +68,20 @@ impl UserDB {
let thread_user_id = get_user_id(); let thread_user_id = get_user_id();
if thread_user_id != Some(user_id.to_owned()) { if thread_user_id != Some(user_id.to_owned()) {
let msg = format!( let msg = format!(
"DataBase owner does not match. origin: {:?}, current: {}", "Database owner does not match. origin: {:?}, current: {}",
thread_user_id, user_id thread_user_id, user_id
); );
log::error!("{}", msg); log::error!("{}", msg);
return Err(UserError::DBConnection(msg)); return Err(UserError::Database(msg));
} }
let read_guard = USER_DB_INNER.read()?; let read_guard = DB
.read()
.map_err(|e| UserError::Database(format!("Get user db connection fail. {:?}", e)))?;
match read_guard.as_ref() { match read_guard.as_ref() {
None => Err(UserError::DBNotInit), None => Err(UserError::Database(
"Database is not initialization".to_owned(),
)),
Some(database) => Ok(database.get_connection()?), Some(database) => Ok(database.get_connection()?),
} }
} }

View File

@ -0,0 +1,3 @@
pub mod database;
mod register;
pub mod user_session;

View File

@ -0,0 +1,22 @@
use crate::{
domain::{tables::User, SignUpParams},
errors::UserError,
};
pub trait UserRegister {
fn register_user(&self, params: SignUpParams) -> Result<User, UserError>;
}
pub struct MockUserRegister {}
impl UserRegister for MockUserRegister {
fn register_user(&self, params: SignUpParams) -> Result<User, UserError> {
let user_id = "9527".to_owned();
Ok(User::new(
user_id,
params.name,
params.email,
params.password,
))
}
}

View File

@ -0,0 +1,23 @@
use crate::services::{
register::MockUserRegister,
user_session::{UserSession, UserSessionConfig},
};
pub struct UserSessionBuilder {
config: Option<UserSessionConfig>,
}
impl UserSessionBuilder {
pub fn new() -> Self { Self { config: None } }
pub fn root_dir(mut self, dir: &str) -> Self {
self.config = Some(UserSessionConfig::new(dir));
self
}
pub fn build(mut self) -> UserSession {
let config = self.config.take().unwrap();
let register = MockUserRegister {};
UserSession::new(config, register)
}
}

View File

@ -0,0 +1,5 @@
mod builder;
mod user_session;
pub use builder::*;
pub use user_session::*;

View File

@ -0,0 +1,86 @@
use crate::{
domain::{tables::User, SignUpParams},
errors::UserError,
services::{database::UserDB, register::UserRegister},
};
use ::diesel::query_dsl::*;
use flowy_database::schema::user_table;
use flowy_sqlite::DBConnection;
use lazy_static::lazy_static;
use std::sync::RwLock;
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,
register: Box<dyn UserRegister + Send + Sync>,
}
impl UserSession {
pub fn new<R>(config: UserSessionConfig, register: R) -> Self
where
R: 'static + UserRegister + Send + Sync,
{
let db = UserDB::new(&config.root_dir);
Self {
database: db,
config,
register: Box::new(register),
}
}
pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
match get_current_user_id()? {
None => Err(UserError::Auth("User is not login yet".to_owned())),
Some(user_id) => self.database.get_connection(&user_id),
}
}
pub fn sign_up(&self, params: SignUpParams) -> Result<User, UserError> {
let user = self.register.register_user(params)?;
set_current_user_id(Some(user.id.clone()));
let conn = self.get_db_connection()?;
let _ = diesel::insert_into(user_table::table)
.values(user.clone())
.execute(&*conn)?;
Ok(user)
}
pub fn sign_out(&self) -> Result<(), UserError> {
set_current_user_id(None);
// TODO: close the db
unimplemented!()
}
}
lazy_static! {
pub static ref CURRENT_USER_ID: RwLock<Option<String>> = RwLock::new(None);
}
fn get_current_user_id() -> Result<Option<String>, UserError> {
let current_user_id = CURRENT_USER_ID
.read()
.map_err(|e| UserError::Auth(format!("Read current user id failed. {:?}", e)))?;
Ok((*current_user_id).clone())
}
pub fn set_current_user_id(user_id: Option<String>) -> Result<(), UserError> {
let mut current_user_id = CURRENT_USER_ID
.write()
.map_err(|e| UserError::Auth(format!("Write current user id failed. {:?}", e)))?;
*current_user_id = user_id;
Ok(())
}

View File

@ -9,11 +9,9 @@ fn sign_up_success() {
password: valid_password(), password: valid_password(),
}; };
let response = EventTester::new(SignUp) let response = EventTester::new(SignUp).request(request).sync_send();
.request(request) // .parse::<SignUpResponse>();
.sync_send() // dbg!(&response);
.parse::<SignUpResponse>();
dbg!(&response);
} }
#[test] #[test]

View File

@ -1 +1 @@
mod auth; mod auth_test;