add create app test & create default workspace when user login at first time

This commit is contained in:
appflowy 2021-07-19 21:05:49 +08:00
parent 139222ddcb
commit 55fad84590
25 changed files with 266 additions and 113 deletions

View File

@ -24,6 +24,7 @@ class UserErrorCode extends $pb.ProtobufEnum {
static const UserErrorCode UserNameInvalid = UserErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameInvalid');
static const UserErrorCode UserWorkspaceInvalid = UserErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid');
static const UserErrorCode UserIdInvalid = UserErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
static const UserErrorCode CreateDefaultWorkspaceFailed = UserErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed');
static const $core.List<UserErrorCode> values = <UserErrorCode> [
Unknown,
@ -40,6 +41,7 @@ class UserErrorCode extends $pb.ProtobufEnum {
UserNameInvalid,
UserWorkspaceInvalid,
UserIdInvalid,
CreateDefaultWorkspaceFailed,
];
static final $core.Map<$core.int, UserErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);

View File

@ -26,11 +26,12 @@ const UserErrorCode$json = const {
const {'1': 'UserNameInvalid', '2': 22},
const {'1': 'UserWorkspaceInvalid', '2': 23},
const {'1': 'UserIdInvalid', '2': 24},
const {'1': 'CreateDefaultWorkspaceFailed', '2': 25},
],
};
/// Descriptor for `UserErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List userErrorCodeDescriptor = $convert.base64Decode('Cg1Vc2VyRXJyb3JDb2RlEgsKB1Vua25vd24QABIaChZVc2VyRGF0YWJhc2VJbml0RmFpbGVkEAESGwoXVXNlckRhdGFiYXNlV3JpdGVMb2NrZWQQAhIaChZVc2VyRGF0YWJhc2VSZWFkTG9ja2VkEAMSGwoXVXNlckRhdGFiYXNlRGlkTm90TWF0Y2gQBBIdChlVc2VyRGF0YWJhc2VJbnRlcm5hbEVycm9yEAUSEwoPVXNlck5vdExvZ2luWWV0EAoSFwoTUmVhZEN1cnJlbnRJZEZhaWxlZBALEhgKFFdyaXRlQ3VycmVudElkRmFpbGVkEAwSEAoMRW1haWxJbnZhbGlkEBQSEwoPUGFzc3dvcmRJbnZhbGlkEBUSEwoPVXNlck5hbWVJbnZhbGlkEBYSGAoUVXNlcldvcmtzcGFjZUludmFsaWQQFxIRCg1Vc2VySWRJbnZhbGlkEBg=');
final $typed_data.Uint8List userErrorCodeDescriptor = $convert.base64Decode('Cg1Vc2VyRXJyb3JDb2RlEgsKB1Vua25vd24QABIaChZVc2VyRGF0YWJhc2VJbml0RmFpbGVkEAESGwoXVXNlckRhdGFiYXNlV3JpdGVMb2NrZWQQAhIaChZVc2VyRGF0YWJhc2VSZWFkTG9ja2VkEAMSGwoXVXNlckRhdGFiYXNlRGlkTm90TWF0Y2gQBBIdChlVc2VyRGF0YWJhc2VJbnRlcm5hbEVycm9yEAUSEwoPVXNlck5vdExvZ2luWWV0EAoSFwoTUmVhZEN1cnJlbnRJZEZhaWxlZBALEhgKFFdyaXRlQ3VycmVudElkRmFpbGVkEAwSEAoMRW1haWxJbnZhbGlkEBQSEwoPUGFzc3dvcmRJbnZhbGlkEBUSEwoPVXNlck5hbWVJbnZhbGlkEBYSGAoUVXNlcldvcmtzcGFjZUludmFsaWQQFxIRCg1Vc2VySWRJbnZhbGlkEBgSIAocQ3JlYXRlRGVmYXVsdFdvcmtzcGFjZUZhaWxlZBAZ');
@$core.Deprecated('Use userErrorDescriptor instead')
const UserError$json = const {
'1': 'UserError',

View File

@ -12,10 +12,12 @@ import 'package:protobuf/protobuf.dart' as $pb;
class WorkspaceEvent extends $pb.ProtobufEnum {
static const WorkspaceEvent CreateWorkspace = WorkspaceEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateWorkspace');
static const WorkspaceEvent GetWorkspaceDetail = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetWorkspaceDetail');
static const WorkspaceEvent CreateApp = WorkspaceEvent._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateApp');
static const $core.List<WorkspaceEvent> values = <WorkspaceEvent> [
CreateWorkspace,
GetWorkspaceDetail,
CreateApp,
];
static final $core.Map<$core.int, WorkspaceEvent> _byValue = $pb.ProtobufEnum.initByValue(values);

View File

@ -14,8 +14,9 @@ const WorkspaceEvent$json = const {
'2': const [
const {'1': 'CreateWorkspace', '2': 0},
const {'1': 'GetWorkspaceDetail', '2': 1},
const {'1': 'CreateApp', '2': 101},
],
};
/// Descriptor for `WorkspaceEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABIWChJHZXRXb3Jrc3BhY2VEZXRhaWwQAQ==');
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABIWChJHZXRXb3Jrc3BhY2VEZXRhaWwQARINCglDcmVhdGVBcHAQZQ==');

View File

@ -1,7 +1,7 @@
use crate::{
errors::{DispatchError, Error, InternalError},
module::{as_module_map, Module, ModuleMap, ModuleRequest},
response::{EventResponse, Responder},
response::EventResponse,
service::{Service, ServiceFactory},
util::tokio_default_runtime,
};

View File

@ -1,4 +1,3 @@
use crate::byte_trait::ToBytes;
use bytes::Bytes;
use std::{fmt, fmt::Formatter};

View File

@ -1,9 +1,15 @@
use flowy_dispatch::prelude::{DispatchFuture, EventDispatch, ModuleRequest, ToBytes};
use flowy_user::{
entities::{SignInParams, SignUpParams, UserDetail},
errors::{ErrorBuilder, UserError, UserErrorCode},
prelude::UserServer,
sql_tables::UserTable,
};
use flowy_workspace::{
entities::workspace::{CreateWorkspaceRequest, WorkspaceDetail},
errors::WorkspaceError,
event::WorkspaceEvent::CreateWorkspace,
};
pub type ArcFlowyServer = std::sync::Arc<dyn FlowyServer>;
@ -34,11 +40,40 @@ impl UserServer for FlowyServerMocker {
))
}
fn sign_out(&self, _user_id: &str) -> Result<(), UserError> {
Err(ErrorBuilder::new(UserErrorCode::Unknown).build())
}
fn get_user_info(&self, _user_id: &str) -> Result<UserDetail, UserError> {
Err(ErrorBuilder::new(UserErrorCode::Unknown).build())
}
fn sign_out(&self, _user_id: &str) -> Result<(), UserError> {
Err(ErrorBuilder::new(UserErrorCode::Unknown).build())
fn create_workspace(
&self,
name: &str,
desc: &str,
_user_id: &str,
) -> DispatchFuture<Result<(), UserError>> {
let payload: Vec<u8> = CreateWorkspaceRequest {
name: name.to_string(),
desc: desc.to_string(),
}
.into_bytes()
.unwrap();
let request = ModuleRequest::new(CreateWorkspace).payload(payload);
DispatchFuture {
fut: Box::pin(async move {
let _ = EventDispatch::async_send(request)
.await
.parse::<WorkspaceDetail, WorkspaceError>()
.map_err(|e| {
ErrorBuilder::new(UserErrorCode::CreateDefaultWorkspaceFailed)
.error(e)
.build()
})?;
Ok(())
}),
}
}
}

View File

@ -3,7 +3,6 @@ mod flowy_server;
pub mod module;
pub use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker};
use deps_resolve::*;
use flowy_dispatch::prelude::*;
use module::build_modules;
pub use module::*;

View File

@ -1,11 +1,9 @@
use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker};
use flowy_database::DBConnection;
use flowy_dispatch::prelude::{DispatchFuture, Module};
use flowy_dispatch::prelude::Module;
use flowy_user::prelude::*;
use flowy_workspace::prelude::*;
use crate::deps_resolve::WorkspaceUserImpl;
use flowy_workspace::entities::workspace::UserWorkspace;
use std::sync::Arc;
pub struct ModuleConfig {

View File

@ -1,4 +1,4 @@
use crate::{conn_ext::*, errors::*, pragma::*};
use crate::{errors::*, pragma::*};
use diesel::{connection::Connection, SqliteConnection};
use r2d2::{CustomizeConnection, ManageConnection, Pool};
use scheduled_thread_pool::ScheduledThreadPool;

View File

@ -11,17 +11,19 @@ use crate::{
};
use flowy_user::errors::UserError;
use flowy_workspace::errors::WorkspaceError;
use std::marker::PhantomData;
use std::{marker::PhantomData, sync::Once};
static INIT: Once = Once::new();
pub type WorkspaceTestBuilder = TestBuilder<FixedUserTester<WorkspaceError>>;
impl WorkspaceTestBuilder {
pub fn new() -> Self {
let builder = Self {
let mut builder = Self {
tester: Box::new(FixedUserTester::<WorkspaceError>::new()),
user_detail: None,
};
builder.login_if_need()
INIT.call_once(|| builder.login_if_need());
builder
}
}
@ -36,7 +38,7 @@ impl UserTestBuilder {
builder
}
pub fn reset(mut self) -> Self { self.logout().login() }
pub fn reset(mut self) -> Self { self.login() }
}
pub struct TestBuilder<T: TesterTrait> {
@ -54,14 +56,13 @@ where
self
}
pub fn login_if_need(mut self) -> Self {
pub fn login_if_need(&mut self) {
let user_detail = self.tester.login_if_need();
self.user_detail = Some(user_detail);
self
}
pub fn logout(self) -> Self {
self.tester.logout();
// self.tester.logout();
self
}

View File

@ -53,6 +53,8 @@ pub enum UserErrorCode {
UserWorkspaceInvalid = 23,
#[display(fmt = "User id is invalid")]
UserIdInvalid = 24,
#[display(fmt = "Create user default workspace failed")]
CreateDefaultWorkspaceFailed = 25,
}
impl std::default::Default for UserErrorCode {
@ -66,9 +68,38 @@ impl std::convert::From<flowy_database::result::Error> for UserError {
.build()
}
}
use diesel::result::DatabaseErrorKind;
impl std::convert::From<flowy_sqlite::Error> for UserError {
fn from(error: flowy_sqlite::Error) -> Self {
// match error.kind() {
// ErrorKind::Msg(_) => {},
// ErrorKind::R2D2(_) => {},
// ErrorKind::Migrations(_) => {},
// ErrorKind::Diesel(diesel_err) => match diesel_err {
// Error::InvalidCString(_) => {},
// Error::DatabaseError(kind, _) => {
// match kind {
// DatabaseErrorKind::UniqueViolation => {
//
// }
// _ => {}
// }
//
// },
// Error::NotFound => {},
// Error::QueryBuilderError(_) => {},
// Error::DeserializationError(_) => {},
// Error::SerializationError(_) => {},
// Error::RollbackTransaction => {},
// Error::AlreadyInTransaction => {},
// Error::__Nonexhaustive => {},
// },
// ErrorKind::Connection(_) => {},
// ErrorKind::Io(_) => {},
// ErrorKind::UnknownMigrationExists(_) => {},
// ErrorKind::__Nonexhaustive { .. } => {},
// }
ErrorBuilder::new(UserErrorCode::UserDatabaseInternalError)
.error(error)
.build()

View File

@ -15,7 +15,7 @@ pub async fn user_sign_in_handler(
session: ModuleData<Arc<UserSession>>,
) -> ResponseResult<UserDetail, UserError> {
let params: SignInParams = data.into_inner().try_into()?;
let user = session.sign_in(params)?;
let user = session.sign_in(params).await?;
let user_detail = UserDetail::from(user);
response_ok(user_detail)
}
@ -33,7 +33,7 @@ pub async fn user_sign_up_handler(
session: ModuleData<Arc<UserSession>>,
) -> ResponseResult<UserDetail, UserError> {
let params: SignUpParams = data.into_inner().try_into()?;
let user = session.sign_up(params)?;
let user = session.sign_up(params).await?;
let user_detail = UserDetail::from(user);
response_ok(user_detail)
}

View File

@ -229,6 +229,7 @@ pub enum UserErrorCode {
UserNameInvalid = 22,
UserWorkspaceInvalid = 23,
UserIdInvalid = 24,
CreateDefaultWorkspaceFailed = 25,
}
impl ::protobuf::ProtobufEnum for UserErrorCode {
@ -252,6 +253,7 @@ impl ::protobuf::ProtobufEnum for UserErrorCode {
22 => ::std::option::Option::Some(UserErrorCode::UserNameInvalid),
23 => ::std::option::Option::Some(UserErrorCode::UserWorkspaceInvalid),
24 => ::std::option::Option::Some(UserErrorCode::UserIdInvalid),
25 => ::std::option::Option::Some(UserErrorCode::CreateDefaultWorkspaceFailed),
_ => ::std::option::Option::None
}
}
@ -272,6 +274,7 @@ impl ::protobuf::ProtobufEnum for UserErrorCode {
UserErrorCode::UserNameInvalid,
UserErrorCode::UserWorkspaceInvalid,
UserErrorCode::UserIdInvalid,
UserErrorCode::CreateDefaultWorkspaceFailed,
];
values
}
@ -302,7 +305,7 @@ impl ::protobuf::reflect::ProtobufValue for UserErrorCode {
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"A\n\tUserError\x12\"\n\x04code\x18\x01\x20\x01(\x0e2\
\x0e.UserErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\
\xde\x02\n\rUserErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16UserDa\
\x80\x03\n\rUserErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16UserDa\
tabaseInitFailed\x10\x01\x12\x1b\n\x17UserDatabaseWriteLocked\x10\x02\
\x12\x1a\n\x16UserDatabaseReadLocked\x10\x03\x12\x1b\n\x17UserDatabaseDi\
dNotMatch\x10\x04\x12\x1d\n\x19UserDatabaseInternalError\x10\x05\x12\x13\
@ -310,43 +313,46 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x18\n\x14WriteCurrentIdFailed\x10\x0c\x12\x10\n\x0cEmailInvalid\x10\x14\
\x12\x13\n\x0fPasswordInvalid\x10\x15\x12\x13\n\x0fUserNameInvalid\x10\
\x16\x12\x18\n\x14UserWorkspaceInvalid\x10\x17\x12\x11\n\rUserIdInvalid\
\x10\x18J\xee\x05\n\x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\x12\x03\0\0\
\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\
\x02\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x1b\n\x0c\n\x05\x04\
\0\x02\0\x06\x12\x03\x03\x04\x11\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\
\x12\x16\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x19\x1a\n\x0b\n\x04\x04\
\0\x02\x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\
\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\
\0\x02\x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x15\x01\
\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\
\x07\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\
\x05\0\x02\0\x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\
\x08\x04\x1f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x1a\n\x0c\n\
\x05\x05\0\x02\x01\x02\x12\x03\x08\x1d\x1e\n\x0b\n\x04\x05\0\x02\x02\x12\
\x03\t\x04\x20\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x1b\n\x0c\n\
\x05\x05\0\x02\x02\x02\x12\x03\t\x1e\x1f\n\x0b\n\x04\x05\0\x02\x03\x12\
\x03\n\x04\x1f\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x1a\n\x0c\n\
\x05\x05\0\x02\x03\x02\x12\x03\n\x1d\x1e\n\x0b\n\x04\x05\0\x02\x04\x12\
\x03\x0b\x04\x20\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x1b\n\x0c\
\n\x05\x05\0\x02\x04\x02\x12\x03\x0b\x1e\x1f\n\x0b\n\x04\x05\0\x02\x05\
\x12\x03\x0c\x04\"\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x1d\n\
\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c\x20!\n\x0b\n\x04\x05\0\x02\x06\
\x12\x03\r\x04\x19\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\
\n\x05\x05\0\x02\x06\x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\
\x03\x0e\x04\x1d\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x17\n\x0c\
\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x1a\x1c\n\x0b\n\x04\x05\0\x02\x08\
\x12\x03\x0f\x04\x1e\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x18\n\
\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x1b\x1d\n\x0b\n\x04\x05\0\x02\t\
\x12\x03\x10\x04\x16\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x10\n\
\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\x13\x15\n\x0b\n\x04\x05\0\x02\n\
\x12\x03\x11\x04\x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x13\n\
\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\x02\x0b\
\x12\x03\x12\x04\x19\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x13\n\
\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x16\x18\n\x0b\n\x04\x05\0\x02\
\x0c\x12\x03\x13\x04\x1e\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x04\
\x18\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x1b\x1d\n\x0b\n\x04\x05\0\
\x02\r\x12\x03\x14\x04\x17\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x04\
\x11\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x14\x16b\x06proto3\
\x10\x18\x12\x20\n\x1cCreateDefaultWorkspaceFailed\x10\x19J\x97\x06\n\
\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\
\x04\x04\0\x02\0\x12\x03\x03\x04\x1b\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\
\x03\x04\x11\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x12\x16\n\x0c\n\x05\
\x04\0\x02\0\x03\x12\x03\x03\x19\x1a\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\
\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
\x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x16\x01\n\n\n\x03\x05\0\
\x01\x12\x03\x06\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x10\n\
\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\0\x02\0\
\x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1f\n\
\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x1a\n\x0c\n\x05\x05\0\x02\
\x01\x02\x12\x03\x08\x1d\x1e\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x20\
\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x1b\n\x0c\n\x05\x05\0\x02\
\x02\x02\x12\x03\t\x1e\x1f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1f\n\
\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\
\x02\x12\x03\n\x1d\x1e\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x20\n\
\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x1b\n\x0c\n\x05\x05\0\x02\
\x04\x02\x12\x03\x0b\x1e\x1f\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x0c\x04\"\
\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x1d\n\x0c\n\x05\x05\0\x02\
\x05\x02\x12\x03\x0c\x20!\n\x0b\n\x04\x05\0\x02\x06\x12\x03\r\x04\x19\n\
\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\x02\x06\
\x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\x1d\n\
\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x17\n\x0c\n\x05\x05\0\x02\
\x07\x02\x12\x03\x0e\x1a\x1c\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\x04\
\x1e\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x18\n\x0c\n\x05\x05\0\
\x02\x08\x02\x12\x03\x0f\x1b\x1d\n\x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04\
\x16\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x10\n\x0c\n\x05\x05\0\
\x02\t\x02\x12\x03\x10\x13\x15\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\
\x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\0\
\x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\x04\
\x19\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x05\0\
\x02\x0b\x02\x12\x03\x12\x16\x18\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x13\
\x04\x1e\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x04\x18\n\x0c\n\x05\
\x05\0\x02\x0c\x02\x12\x03\x13\x1b\x1d\n\x0b\n\x04\x05\0\x02\r\x12\x03\
\x14\x04\x17\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x04\x11\n\x0c\n\x05\
\x05\0\x02\r\x02\x12\x03\x14\x14\x16\n\x0b\n\x04\x05\0\x02\x0e\x12\x03\
\x15\x04&\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\x15\x04\x20\n\x0c\n\x05\
\x05\0\x02\x0e\x02\x12\x03\x15#%b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -19,4 +19,5 @@ enum UserErrorCode {
UserNameInvalid = 22;
UserWorkspaceInvalid = 23;
UserIdInvalid = 24;
CreateDefaultWorkspaceFailed = 25;
}

View File

@ -3,10 +3,21 @@ use crate::{
errors::UserError,
sql_tables::UserTable,
};
use flowy_dispatch::prelude::DispatchFuture;
pub trait UserServer {
fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError>;
fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError>;
fn get_user_info(&self, user_id: &str) -> Result<UserDetail, UserError>;
fn sign_out(&self, user_id: &str) -> Result<(), UserError>;
fn get_user_info(&self, user_id: &str) -> Result<UserDetail, UserError>;
fn create_workspace(
&self,
name: &str,
desc: &str,
user_id: &str,
) -> DispatchFuture<Result<(), UserError>>;
}

View File

@ -18,6 +18,10 @@ use crate::{
};
use flowy_dispatch::prelude::{EventDispatch, ModuleRequest, ToBytes};
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";
pub struct UserSessionConfig {
root_dir: String,
}
@ -56,17 +60,25 @@ impl UserSession {
self.database.get_connection(&user_id)
}
pub fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError> {
pub async fn sign_in(&self, params: SignInParams) -> Result<UserTable, UserError> {
let user = self.server.sign_in(params)?;
let _ = self.set_user_id(Some(user.id.clone()))?;
self.save_user(user)
let user_table = self.save_user(user)?;
let _ = self
.create_default_workspace_if_need(&user_table.id)
.await?;
Ok(user_table)
}
pub fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError> {
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserTable, UserError> {
let user = self.server.sign_up(params)?;
let _ = self.set_user_id(Some(user.id.clone()))?;
self.save_user(user)
let user_table = self.save_user(user)?;
let _ = self
.create_default_workspace_if_need(&user_table.id)
.await?;
Ok(user_table)
}
pub fn sign_out(&self) -> Result<(), UserError> {
@ -147,7 +159,7 @@ impl UserSession {
if user_id.is_none() {
user_id = KVStore::get_str(USER_ID_CACHE_KEY);
self.set_user_id(user_id.clone());
let _ = self.set_user_id(user_id.clone())?;
}
match user_id {
@ -170,6 +182,21 @@ impl UserSession {
.unwrap()?;
Ok(())
}
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(())
}
}
pub fn current_user_id() -> Result<String, UserError> {

View File

@ -5,7 +5,6 @@ use serial_test::*;
#[test]
#[serial]
fn sign_up_success() {
let _ = UserTestBuilder::new().event(SignOut).sync_send();
let request = SignUpRequest {
email: random_valid_email(),
name: valid_name(),
@ -17,8 +16,6 @@ fn sign_up_success() {
.event(SignUp)
.request(request)
.sync_send();
// .parse::<SignUpResponse>();
// dbg!(&response);
}
#[test]

View File

@ -3,14 +3,13 @@ use flowy_user::{event::UserEvent::*, prelude::*};
use serial_test::*;
#[test]
#[should_panic]
#[serial]
fn user_status_get_failed_before_login() {
let _ = UserTestBuilder::new()
let a = UserTestBuilder::new()
.logout()
.event(GetStatus)
.sync_send()
.parse::<UserDetail>();
.assert_error()
.sync_send();
}
#[test]

View File

@ -11,4 +11,8 @@ pub enum WorkspaceEvent {
#[display(fmt = "Get user's workspace detail")]
#[event(output = "UserWorkspaceDetail")]
GetWorkspaceDetail = 1,
#[display(fmt = "Create app")]
#[event(input = "CreateAppRequest", output = "AppDetail")]
CreateApp = 101,
}

View File

@ -26,4 +26,5 @@ pub fn create(user: Arc<dyn WorkspaceUser>) -> Module {
.data(app_controller)
.event(WorkspaceEvent::CreateWorkspace, create_workspace)
.event(WorkspaceEvent::GetWorkspaceDetail, get_workspace_detail)
.event(WorkspaceEvent::CreateApp, create_app)
}

View File

@ -27,6 +27,7 @@
pub enum WorkspaceEvent {
CreateWorkspace = 0,
GetWorkspaceDetail = 1,
CreateApp = 101,
}
impl ::protobuf::ProtobufEnum for WorkspaceEvent {
@ -38,6 +39,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
match value {
0 => ::std::option::Option::Some(WorkspaceEvent::CreateWorkspace),
1 => ::std::option::Option::Some(WorkspaceEvent::GetWorkspaceDetail),
101 => ::std::option::Option::Some(WorkspaceEvent::CreateApp),
_ => ::std::option::Option::None
}
}
@ -46,6 +48,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
static values: &'static [WorkspaceEvent] = &[
WorkspaceEvent::CreateWorkspace,
WorkspaceEvent::GetWorkspaceDetail,
WorkspaceEvent::CreateApp,
];
values
}
@ -74,14 +77,17 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0bevent.proto*=\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorkspace\x10\
\0\x12\x16\n\x12GetWorkspaceDetail\x10\x01J|\n\x06\x12\x04\0\0\x05\x01\n\
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x05\x01\n\n\
\n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\
\x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x13\n\x0c\n\x05\x05\
\0\x02\0\x02\x12\x03\x03\x16\x17\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\
\x04\x1b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x16\n\x0c\n\x05\
\x05\0\x02\x01\x02\x12\x03\x04\x19\x1ab\x06proto3\
\n\x0bevent.proto*L\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorkspace\x10\
\0\x12\x16\n\x12GetWorkspaceDetail\x10\x01\x12\r\n\tCreateApp\x10eJ\xa5\
\x01\n\x06\x12\x04\0\0\x06\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
\x05\0\x12\x04\x02\0\x06\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\
\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\
\x12\x03\x03\x04\x13\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x16\x17\n\
\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x1b\n\x0c\n\x05\x05\0\x02\x01\
\x01\x12\x03\x04\x04\x16\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x19\
\x1a\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x05\0\x02\
\x02\x01\x12\x03\x05\x04\r\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x10\
\x13b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -3,4 +3,5 @@ syntax = "proto3";
enum WorkspaceEvent {
CreateWorkspace = 0;
GetWorkspaceDetail = 1;
CreateApp = 101;
}

View File

@ -1,15 +1,33 @@
// #[test]
// fn app_create_success() {
// let request = CreateAppRequest {
// workspace_id: "".to_string(),
// name: "123".to_owned(),
// desc: "".to_owned(),
// color_style: Default::default(),
// };
//
// let response = WorkspaceEventTester::new(CreateWorkspace)
// .request(request)
// .sync_send()
// .parse::<WorkspaceDetail>();
// dbg!(&response);
// }
use flowy_test::builder::WorkspaceTestBuilder;
use flowy_workspace::{
entities::{
app::{AppDetail, CreateAppRequest},
workspace::UserWorkspaceDetail,
},
event::WorkspaceEvent::{CreateApp, GetWorkspaceDetail},
};
#[test]
fn app_create_success() {
let user_workspace = WorkspaceTestBuilder::new()
.event(GetWorkspaceDetail)
.sync_send()
.parse::<UserWorkspaceDetail>();
let request = CreateAppRequest {
workspace_id: user_workspace.workspace.id,
name: "Github".to_owned(),
desc: "AppFlowy Github Project".to_owned(),
color_style: Default::default(),
};
let app_detail = WorkspaceTestBuilder::new()
.event(CreateApp)
.request(request)
.sync_send()
.parse::<AppDetail>();
dbg!(&app_detail);
}
// TODO 1) test update app 2) delete app

View File

@ -22,6 +22,16 @@ fn workspace_create_success() {
#[test]
fn workspace_get_detail_success() {
let user_workspace = WorkspaceTestBuilder::new()
.event(GetWorkspaceDetail)
.sync_send()
.parse::<UserWorkspaceDetail>();
dbg!(&user_workspace);
}
#[test]
fn workspace_create_and_then_get_detail_success() {
let request = CreateWorkspaceRequest {
name: "Team A".to_owned(),
desc: "Team A Description".to_owned(),
@ -61,21 +71,24 @@ fn workspace_create_with_invalid_name_test() {
}
}
// #[test]
// fn workspace_update_with_invalid_name_test() {
// for name in invalid_workspace_name_test_case() {
// let request = CreateWorkspaceRequest {
// name,
// desc: "".to_owned(),
// };
//
// assert_eq!(
// WorkspaceEventTester::new(CreateWorkspace)
// .request(request)
// .sync_send()
// .error()
// .code,
// WorkspaceErrorCode::WorkspaceNameInvalid
// )
// }
// }
#[test]
fn workspace_update_with_invalid_name_test() {
for name in invalid_workspace_name_test_case() {
let request = CreateWorkspaceRequest {
name,
desc: "".to_owned(),
};
assert_eq!(
WorkspaceTestBuilder::new()
.event(CreateWorkspace)
.request(request)
.sync_send()
.error()
.code,
WorkspaceErrorCode::WorkspaceNameInvalid
)
}
}
// TODO 1) delete workspace, but can't delete the last workspace