From 139a21d98a38a7b27b4de7e71f6599f5b936b863 Mon Sep 17 00:00:00 2001
From: appflowy <annie@appflowy.io>
Date: Fri, 20 Aug 2021 11:52:45 +0800
Subject: [PATCH] add flowy-net crate shared code by server and client

---
 Makefile                                      |   0
 .../lib/protobuf/flowy-user/sign_up.pb.dart   |  30 +++--
 .../protobuf/flowy-user/sign_up.pbjson.dart   |   5 +-
 backend/Cargo.toml                            |   3 +-
 backend/src/entities/mod.rs                   |   6 -
 backend/src/entities/server_code.rs           |  12 --
 backend/src/errors.rs                         |  48 -------
 backend/src/lib.rs                            |   1 -
 backend/src/routers/helper.rs                 |   7 +-
 backend/src/routers/user.rs                   |  15 ++-
 backend/src/user_service/auth.rs              |   6 +-
 backend/src/ws_service/entities/connect.rs    |   3 +-
 backend/src/ws_service/ws_server.rs           |  10 +-
 rust-lib/Cargo.toml                           |   1 +
 rust-lib/dart-ffi/src/protobuf/mod.rs         |   2 -
 rust-lib/dart-ffi/src/protobuf/model/mod.rs   |  10 +-
 .../src/derive_cache/derive_cache.rs          |   6 +-
 rust-lib/flowy-dispatch/src/service/boxed.rs  |   2 +-
 .../flowy-dispatch/src/service/service.rs     |   4 +-
 rust-lib/flowy-dispatch/src/util/ready.rs     |  16 +--
 rust-lib/flowy-document/src/protobuf/mod.rs   |   2 -
 .../flowy-document/src/protobuf/model/mod.rs  |  22 +--
 rust-lib/flowy-infra/src/protobuf/mod.rs      |   2 -
 .../flowy-infra/src/protobuf/model/mod.rs     |   6 +-
 rust-lib/flowy-net/Cargo.toml                 |  17 +++
 rust-lib/flowy-net/src/errors.rs              |  30 +++++
 rust-lib/flowy-net/src/lib.rs                 |   2 +
 rust-lib/flowy-net/src/response/mod.rs        |   7 +
 .../flowy-net/src/response}/response.rs       |  29 ++--
 .../flowy-net/src/response/response_http.rs   |  31 +++++
 .../flowy-net/src/response}/response_serde.rs |   2 +-
 .../flowy-observable/src/entities/subject.rs  |   2 +-
 rust-lib/flowy-observable/src/protobuf/mod.rs |   2 -
 .../src/protobuf/model/mod.rs                 |   6 +-
 rust-lib/flowy-ot/src/server/mod.rs           |   1 +
 rust-lib/flowy-user/src/entities/sign_up.rs   |   7 +-
 rust-lib/flowy-user/src/protobuf/mod.rs       |   2 -
 rust-lib/flowy-user/src/protobuf/model/mod.rs |  30 ++---
 .../flowy-user/src/protobuf/model/sign_up.rs  | 127 ++++++++++++------
 .../src/protobuf/proto/sign_up.proto          |   3 +-
 rust-lib/flowy-workspace/src/protobuf/mod.rs  |   2 -
 .../flowy-workspace/src/protobuf/model/mod.rs |  66 ++++-----
 .../flowy-workspace/src/services/database.rs  |   1 +
 43 files changed, 325 insertions(+), 261 deletions(-)
 delete mode 100644 Makefile
 delete mode 100644 backend/src/entities/server_code.rs
 delete mode 100644 backend/src/errors.rs
 create mode 100644 rust-lib/flowy-net/Cargo.toml
 create mode 100644 rust-lib/flowy-net/src/errors.rs
 create mode 100644 rust-lib/flowy-net/src/lib.rs
 create mode 100644 rust-lib/flowy-net/src/response/mod.rs
 rename {backend/src/entities => rust-lib/flowy-net/src/response}/response.rs (58%)
 create mode 100644 rust-lib/flowy-net/src/response/response_http.rs
 rename {backend/src/entities => rust-lib/flowy-net/src/response}/response_serde.rs (98%)

diff --git a/Makefile b/Makefile
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pb.dart
index 5eae8d834a..47caf0449b 100644
--- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pb.dart
+++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pb.dart
@@ -161,17 +161,22 @@ class SignUpParams extends $pb.GeneratedMessage {
 
 class SignUpResponse extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SignUpResponse', createEmptyInstance: create)
-    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSuccess')
+    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'email')
     ..hasRequiredFields = false
   ;
 
   SignUpResponse._() : super();
   factory SignUpResponse({
-    $core.bool? isSuccess,
+    $core.bool? name,
+    $core.String? email,
   }) {
     final _result = create();
-    if (isSuccess != null) {
-      _result.isSuccess = isSuccess;
+    if (name != null) {
+      _result.name = name;
+    }
+    if (email != null) {
+      _result.email = email;
     }
     return _result;
   }
@@ -197,12 +202,21 @@ class SignUpResponse extends $pb.GeneratedMessage {
   static SignUpResponse? _defaultInstance;
 
   @$pb.TagNumber(1)
-  $core.bool get isSuccess => $_getBF(0);
+  $core.bool get name => $_getBF(0);
   @$pb.TagNumber(1)
-  set isSuccess($core.bool v) { $_setBool(0, v); }
+  set name($core.bool v) { $_setBool(0, v); }
   @$pb.TagNumber(1)
-  $core.bool hasIsSuccess() => $_has(0);
+  $core.bool hasName() => $_has(0);
   @$pb.TagNumber(1)
-  void clearIsSuccess() => clearField(1);
+  void clearName() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.String get email => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set email($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasEmail() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearEmail() => clearField(2);
 }
 
diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pbjson.dart
index a25f2dd812..61e3e6825c 100644
--- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pbjson.dart
+++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/sign_up.pbjson.dart
@@ -36,9 +36,10 @@ final $typed_data.Uint8List signUpParamsDescriptor = $convert.base64Decode('CgxT
 const SignUpResponse$json = const {
   '1': 'SignUpResponse',
   '2': const [
-    const {'1': 'is_success', '3': 1, '4': 1, '5': 8, '10': 'isSuccess'},
+    const {'1': 'name', '3': 1, '4': 1, '5': 8, '10': 'name'},
+    const {'1': 'email', '3': 2, '4': 1, '5': 9, '10': 'email'},
   ],
 };
 
 /// Descriptor for `SignUpResponse`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List signUpResponseDescriptor = $convert.base64Decode('Cg5TaWduVXBSZXNwb25zZRIdCgppc19zdWNjZXNzGAEgASgIUglpc1N1Y2Nlc3M=');
+final $typed_data.Uint8List signUpResponseDescriptor = $convert.base64Decode('Cg5TaWduVXBSZXNwb25zZRISCgRuYW1lGAEgASgIUgRuYW1lEhQKBWVtYWlsGAIgASgJUgVlbWFpbA==');
diff --git a/backend/Cargo.toml b/backend/Cargo.toml
index 1e0d8b106b..1456d14408 100644
--- a/backend/Cargo.toml
+++ b/backend/Cargo.toml
@@ -24,6 +24,7 @@ derive_more = {version = "0.99", features = ["display"]}
 protobuf = {version = "2.20.0"}
 flowy-log = { path = "../rust-lib/flowy-log" }
 flowy-user = { path = "../rust-lib/flowy-user" }
+flowy-net = { path = "../rust-lib/flowy-net", features = ["http"] }
 
 [dependencies.sqlx]
 version = "0.5.2"
@@ -38,8 +39,6 @@ features = [
 ]
 
 
-
-
 [lib]
 path = "src/lib.rs"
 
diff --git a/backend/src/entities/mod.rs b/backend/src/entities/mod.rs
index 9dbbe4cc26..8b13789179 100644
--- a/backend/src/entities/mod.rs
+++ b/backend/src/entities/mod.rs
@@ -1,7 +1 @@
-mod response;
-mod response_serde;
-mod server_code;
 
-pub use response::*;
-pub use response_serde::*;
-pub use server_code::*;
diff --git a/backend/src/entities/server_code.rs b/backend/src/entities/server_code.rs
deleted file mode 100644
index f0790f0a71..0000000000
--- a/backend/src/entities/server_code.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use serde_repr::*;
-
-#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
-#[repr(u16)]
-pub enum ServerCode {
-    Success          = 0,
-    InvalidToken     = 1,
-    InternalError    = 2,
-    Unauthorized     = 3,
-    PayloadOverflow  = 4,
-    PayloadSerdeFail = 5,
-}
diff --git a/backend/src/errors.rs b/backend/src/errors.rs
deleted file mode 100644
index 5da2cccc23..0000000000
--- a/backend/src/errors.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::entities::{ServerCode, ServerResponse};
-use actix_web::{error::ResponseError, HttpResponse};
-use protobuf::ProtobufError;
-use std::fmt::Formatter;
-
-#[derive(Debug)]
-pub enum ServerError {
-    InternalError(String),
-    BadRequest(ServerResponse<String>),
-    Unauthorized,
-}
-
-impl std::fmt::Display for ServerError {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        match self {
-            ServerError::InternalError(_) => f.write_str("Internal Server Error"),
-            ServerError::BadRequest(request) => {
-                let msg = format!("Bad Request: {:?}", request);
-                f.write_str(&msg)
-            },
-            ServerError::Unauthorized => f.write_str("Unauthorized"),
-        }
-    }
-}
-
-impl ResponseError for ServerError {
-    fn error_response(&self) -> HttpResponse {
-        match self {
-            ServerError::InternalError(msg) => {
-                let msg = format!("Internal Server Error. {}", msg);
-                let resp = ServerResponse::from_msg(&msg, ServerCode::InternalError);
-                HttpResponse::InternalServerError().json(resp)
-            },
-            ServerError::BadRequest(ref resp) => HttpResponse::BadRequest().json(resp),
-            ServerError::Unauthorized => {
-                let resp = ServerResponse::from_msg("Unauthorized", ServerCode::Unauthorized);
-                HttpResponse::Unauthorized().json(resp)
-            },
-        }
-    }
-}
-
-impl std::convert::From<ProtobufError> for ServerError {
-    fn from(err: ProtobufError) -> Self {
-        let msg = format!("{:?}", err);
-        ServerError::InternalError(msg)
-    }
-}
diff --git a/backend/src/lib.rs b/backend/src/lib.rs
index 4333f4ea66..7a4a35d7b1 100644
--- a/backend/src/lib.rs
+++ b/backend/src/lib.rs
@@ -1,7 +1,6 @@
 mod config;
 mod context;
 mod entities;
-mod errors;
 mod routers;
 pub mod startup;
 pub mod user_service;
diff --git a/backend/src/routers/helper.rs b/backend/src/routers/helper.rs
index b7d7fb5de9..03312dc44f 100644
--- a/backend/src/routers/helper.rs
+++ b/backend/src/routers/helper.rs
@@ -1,9 +1,6 @@
-use crate::{
-    config::MAX_PAYLOAD_SIZE,
-    entities::{ServerCode, ServerResponse},
-    errors::ServerError,
-};
+use crate::config::MAX_PAYLOAD_SIZE;
 use actix_web::web;
+use flowy_net::{errors::ServerError, response::*};
 use futures::StreamExt;
 use protobuf::{Message, ProtobufResult};
 
diff --git a/backend/src/routers/user.rs b/backend/src/routers/user.rs
index bc482c1a9e..2f4b901845 100644
--- a/backend/src/routers/user.rs
+++ b/backend/src/routers/user.rs
@@ -1,23 +1,24 @@
-use crate::user_service::Auth;
+use crate::{routers::helper::parse_from_payload, user_service::Auth};
 use actix_web::{
     web::{Data, Payload},
     Error,
     HttpRequest,
     HttpResponse,
 };
-use flowy_user::protobuf::SignUpRequest;
-
-use crate::{entities::ServerResponse, routers::helper::parse_from_payload};
+use flowy_net::response::*;
+use flowy_user::protobuf::SignUpParams;
 
 use std::sync::Arc;
 
 pub async fn user_register(
-    request: HttpRequest,
+    _request: HttpRequest,
     payload: Payload,
     auth: Data<Arc<Auth>>,
 ) -> Result<HttpResponse, Error> {
-    let request: SignUpRequest = parse_from_payload(payload).await?;
-    // ProtobufError
+    let params: SignUpParams = parse_from_payload(payload).await?;
+    let _ = auth.sign_up(params)?;
+
     let resp = ServerResponse::success();
+
     Ok(resp.into())
 }
diff --git a/backend/src/user_service/auth.rs b/backend/src/user_service/auth.rs
index 6ee457a57e..dea84dd3eb 100644
--- a/backend/src/user_service/auth.rs
+++ b/backend/src/user_service/auth.rs
@@ -1,5 +1,5 @@
-use crate::errors::ServerError;
-use flowy_user::protobuf::SignUpRequest;
+use flowy_net::errors::ServerError;
+use flowy_user::protobuf::SignUpParams;
 use sqlx::PgPool;
 use std::sync::Arc;
 
@@ -10,5 +10,5 @@ pub struct Auth {
 impl Auth {
     pub fn new(db_pool: Arc<PgPool>) -> Self { Self { db_pool } }
 
-    pub fn handle_sign_up(&self, request: SignUpRequest) -> Result<(), ServerError> { Ok(()) }
+    pub fn sign_up(&self, params: SignUpParams) -> Result<(), ServerError> { Ok(()) }
 }
diff --git a/backend/src/ws_service/entities/connect.rs b/backend/src/ws_service/entities/connect.rs
index 36e13527d1..10f04b285a 100644
--- a/backend/src/ws_service/entities/connect.rs
+++ b/backend/src/ws_service/entities/connect.rs
@@ -1,5 +1,6 @@
-use crate::{errors::ServerError, ws_service::ClientMessage};
+use crate::ws_service::ClientMessage;
 use actix::{Message, Recipient};
+use flowy_net::errors::ServerError;
 use serde::{Deserialize, Serialize};
 use std::fmt::Formatter;
 
diff --git a/backend/src/ws_service/ws_server.rs b/backend/src/ws_service/ws_server.rs
index 4a254da986..ac307504ad 100644
--- a/backend/src/ws_service/ws_server.rs
+++ b/backend/src/ws_service/ws_server.rs
@@ -1,12 +1,10 @@
-use crate::{
-    errors::ServerError,
-    ws_service::{
-        entities::{Connect, Disconnect, Session, SessionId},
-        ClientMessage,
-    },
+use crate::ws_service::{
+    entities::{Connect, Disconnect, Session, SessionId},
+    ClientMessage,
 };
 use actix::{Actor, Context, Handler};
 use dashmap::DashMap;
+use flowy_net::errors::ServerError;
 
 pub struct WSServer {
     sessions: DashMap<SessionId, Session>,
diff --git a/rust-lib/Cargo.toml b/rust-lib/Cargo.toml
index e8b04407d2..5815cabc35 100644
--- a/rust-lib/Cargo.toml
+++ b/rust-lib/Cargo.toml
@@ -16,6 +16,7 @@ members = [
   "flowy-document",
   "flowy-editor",
   "flowy-ot",
+  "flowy-net",
 ]
 
 [profile.dev]
diff --git a/rust-lib/dart-ffi/src/protobuf/mod.rs b/rust-lib/dart-ffi/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/dart-ffi/src/protobuf/mod.rs
+++ b/rust-lib/dart-ffi/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/dart-ffi/src/protobuf/model/mod.rs b/rust-lib/dart-ffi/src/protobuf/model/mod.rs
index 8220f60f66..faa39cb5d8 100644
--- a/rust-lib/dart-ffi/src/protobuf/model/mod.rs
+++ b/rust-lib/dart-ffi/src/protobuf/model/mod.rs
@@ -1,7 +1,7 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod ffi_response; 
-pub use ffi_response::*; 
+mod ffi_response;
+pub use ffi_response::*;
 
-mod ffi_request; 
-pub use ffi_request::*; 
+mod ffi_request;
+pub use ffi_request::*;
diff --git a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
index 0d7d78aec3..764a23d1c6 100644
--- a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
+++ b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
@@ -54,8 +54,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "SignUpResponse"
         | "SignInRequest"
         | "SignInParams"
-        | "UserError"
-        => TypeCategory::Protobuf,
+        | "UserError" => TypeCategory::Protobuf,
         "ViewType"
         | "WorkspaceEvent"
         | "WsErrCode"
@@ -65,8 +64,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "FFIStatusCode"
         | "UserStatus"
         | "UserEvent"
-        | "UserErrCode"
-        => TypeCategory::Enum,
+        | "UserErrCode" => TypeCategory::Enum,
 
         "Option" => TypeCategory::Opt,
         _ => TypeCategory::Primitive,
diff --git a/rust-lib/flowy-dispatch/src/service/boxed.rs b/rust-lib/flowy-dispatch/src/service/boxed.rs
index 7fcf904070..57e919cbae 100644
--- a/rust-lib/flowy-dispatch/src/service/boxed.rs
+++ b/rust-lib/flowy-dispatch/src/service/boxed.rs
@@ -1,5 +1,5 @@
 use crate::service::{Service, ServiceFactory};
-use futures_core::future::{BoxFuture};
+use futures_core::future::BoxFuture;
 
 pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Context, Req, SF::Response, SF::Error>
 where
diff --git a/rust-lib/flowy-dispatch/src/service/service.rs b/rust-lib/flowy-dispatch/src/service/service.rs
index 740612cd45..6cb3dfb1e6 100644
--- a/rust-lib/flowy-dispatch/src/service/service.rs
+++ b/rust-lib/flowy-dispatch/src/service/service.rs
@@ -41,7 +41,9 @@ pub struct ServiceResponse {
 }
 
 impl ServiceResponse {
-    pub fn new(request: EventRequest, response: EventResponse) -> Self { ServiceResponse { request, response } }
+    pub fn new(request: EventRequest, response: EventResponse) -> Self {
+        ServiceResponse { request, response }
+    }
 
     pub fn into_parts(self) -> (EventRequest, EventResponse) { (self.request, self.response) }
 }
diff --git a/rust-lib/flowy-dispatch/src/util/ready.rs b/rust-lib/flowy-dispatch/src/util/ready.rs
index 991ed19cb7..f6457bc5cf 100644
--- a/rust-lib/flowy-dispatch/src/util/ready.rs
+++ b/rust-lib/flowy-dispatch/src/util/ready.rs
@@ -1,6 +1,8 @@
-use std::future::Future;
-use std::pin::Pin;
-use std::task::{Context, Poll};
+use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
 
 pub struct Ready<T> {
     val: Option<T>,
@@ -8,9 +10,7 @@ pub struct Ready<T> {
 
 impl<T> Ready<T> {
     #[inline]
-    pub fn into_inner(mut self) -> T {
-        self.val.take().unwrap()
-    }
+    pub fn into_inner(mut self) -> T { self.val.take().unwrap() }
 }
 
 impl<T> Unpin for Ready<T> {}
@@ -25,6 +25,4 @@ impl<T> Future for Ready<T> {
     }
 }
 
-pub fn ready<T>(val: T) -> Ready<T> {
-    Ready { val: Some(val) }
-}
+pub fn ready<T>(val: T) -> Ready<T> { Ready { val: Some(val) } }
diff --git a/rust-lib/flowy-document/src/protobuf/mod.rs b/rust-lib/flowy-document/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/flowy-document/src/protobuf/mod.rs
+++ b/rust-lib/flowy-document/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/flowy-document/src/protobuf/model/mod.rs b/rust-lib/flowy-document/src/protobuf/model/mod.rs
index 4bea143a13..4baa1b6450 100644
--- a/rust-lib/flowy-document/src/protobuf/model/mod.rs
+++ b/rust-lib/flowy-document/src/protobuf/model/mod.rs
@@ -1,16 +1,16 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod doc_modify; 
-pub use doc_modify::*; 
+mod doc_modify;
+pub use doc_modify::*;
 
-mod doc_create; 
-pub use doc_create::*; 
+mod doc_create;
+pub use doc_create::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod doc_query; 
-pub use doc_query::*; 
+mod doc_query;
+pub use doc_query::*;
diff --git a/rust-lib/flowy-infra/src/protobuf/mod.rs b/rust-lib/flowy-infra/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/flowy-infra/src/protobuf/mod.rs
+++ b/rust-lib/flowy-infra/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/flowy-infra/src/protobuf/model/mod.rs b/rust-lib/flowy-infra/src/protobuf/model/mod.rs
index b481acecd1..fac22cac7e 100644
--- a/rust-lib/flowy-infra/src/protobuf/model/mod.rs
+++ b/rust-lib/flowy-infra/src/protobuf/model/mod.rs
@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod kv; 
-pub use kv::*; 
+mod kv;
+pub use kv::*;
diff --git a/rust-lib/flowy-net/Cargo.toml b/rust-lib/flowy-net/Cargo.toml
new file mode 100644
index 0000000000..8bd7a61fea
--- /dev/null
+++ b/rust-lib/flowy-net/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "flowy-net"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+reqwest = "0.11"
+protobuf = {version = "2.18.0"}
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+serde_repr = "0.1"
+actix-web = {version = "3", optional = true}
+
+[features]
+http = ["actix-web"]
\ No newline at end of file
diff --git a/rust-lib/flowy-net/src/errors.rs b/rust-lib/flowy-net/src/errors.rs
new file mode 100644
index 0000000000..7a10e3f90a
--- /dev/null
+++ b/rust-lib/flowy-net/src/errors.rs
@@ -0,0 +1,30 @@
+use crate::response::ServerResponse;
+use protobuf::ProtobufError;
+use std::fmt::{Formatter, Write};
+
+#[derive(Debug)]
+pub enum ServerError {
+    InternalError(String),
+    BadRequest(ServerResponse<String>),
+    Unauthorized,
+}
+
+impl std::fmt::Display for ServerError {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        match self {
+            ServerError::InternalError(_) => f.write_str("Internal Server Error"),
+            ServerError::BadRequest(request) => {
+                let msg = format!("Bad Request: {:?}", request);
+                f.write_str(&msg)
+            },
+            ServerError::Unauthorized => f.write_str("Unauthorized"),
+        }
+    }
+}
+
+impl std::convert::From<ProtobufError> for ServerError {
+    fn from(err: ProtobufError) -> Self {
+        let msg = format!("{:?}", err);
+        ServerError::InternalError(msg)
+    }
+}
diff --git a/rust-lib/flowy-net/src/lib.rs b/rust-lib/flowy-net/src/lib.rs
new file mode 100644
index 0000000000..a4493f2acc
--- /dev/null
+++ b/rust-lib/flowy-net/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod errors;
+pub mod response;
diff --git a/rust-lib/flowy-net/src/response/mod.rs b/rust-lib/flowy-net/src/response/mod.rs
new file mode 100644
index 0000000000..ab5f3cfd20
--- /dev/null
+++ b/rust-lib/flowy-net/src/response/mod.rs
@@ -0,0 +1,7 @@
+mod response;
+mod response_serde;
+
+#[cfg(feature = "http")]
+mod response_http;
+
+pub use response::*;
diff --git a/backend/src/entities/response.rs b/rust-lib/flowy-net/src/response/response.rs
similarity index 58%
rename from backend/src/entities/response.rs
rename to rust-lib/flowy-net/src/response/response.rs
index 6a020b101f..3abe22107b 100644
--- a/backend/src/entities/response.rs
+++ b/rust-lib/flowy-net/src/response/response.rs
@@ -1,8 +1,19 @@
-use crate::{entities::ServerCode, errors::ServerError};
-use actix_web::{body::Body, HttpResponse, ResponseError};
-
+use crate::errors::ServerError;
 use serde::Serialize;
 
+use serde_repr::*;
+
+#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
+#[repr(u16)]
+pub enum ServerCode {
+    Success          = 0,
+    InvalidToken     = 1,
+    InternalError    = 2,
+    Unauthorized     = 3,
+    PayloadOverflow  = 4,
+    PayloadSerdeFail = 5,
+}
+
 #[derive(Debug, Serialize)]
 pub struct ServerResponse<T> {
     pub msg: String,
@@ -31,15 +42,3 @@ impl ServerResponse<String> {
         Self::new(Some("".to_owned()), msg, code)
     }
 }
-
-impl<T: Serialize> std::convert::Into<HttpResponse> for ServerResponse<T> {
-    fn into(self) -> HttpResponse {
-        match serde_json::to_string(&self) {
-            Ok(body) => HttpResponse::Ok().body(Body::from(body)),
-            Err(e) => {
-                let msg = format!("Serial error: {:?}", e);
-                ServerError::InternalError(msg).error_response()
-            },
-        }
-    }
-}
diff --git a/rust-lib/flowy-net/src/response/response_http.rs b/rust-lib/flowy-net/src/response/response_http.rs
new file mode 100644
index 0000000000..89fe389f45
--- /dev/null
+++ b/rust-lib/flowy-net/src/response/response_http.rs
@@ -0,0 +1,31 @@
+use crate::{errors::ServerError, response::*};
+use actix_web::{body::Body, error::ResponseError, HttpResponse};
+use serde::Serialize;
+
+impl ResponseError for ServerError {
+    fn error_response(&self) -> HttpResponse {
+        match self {
+            ServerError::InternalError(msg) => {
+                let resp = ServerResponse::from_msg(&msg, ServerCode::InternalError);
+                HttpResponse::InternalServerError().json(resp)
+            },
+            ServerError::BadRequest(ref resp) => HttpResponse::BadRequest().json(resp),
+            ServerError::Unauthorized => {
+                let resp = ServerResponse::from_msg("Unauthorized", ServerCode::Unauthorized);
+                HttpResponse::Unauthorized().json(resp)
+            },
+        }
+    }
+}
+
+impl<T: Serialize> std::convert::Into<HttpResponse> for ServerResponse<T> {
+    fn into(self) -> HttpResponse {
+        match serde_json::to_string(&self) {
+            Ok(body) => HttpResponse::Ok().body(Body::from(body)),
+            Err(e) => {
+                let msg = format!("Serial error: {:?}", e);
+                ServerError::InternalError(msg).error_response()
+            },
+        }
+    }
+}
diff --git a/backend/src/entities/response_serde.rs b/rust-lib/flowy-net/src/response/response_serde.rs
similarity index 98%
rename from backend/src/entities/response_serde.rs
rename to rust-lib/flowy-net/src/response/response_serde.rs
index 7149fa0980..0ab1c61e75 100644
--- a/backend/src/entities/response_serde.rs
+++ b/rust-lib/flowy-net/src/response/response_serde.rs
@@ -1,4 +1,4 @@
-use crate::entities::{ServerCode, ServerResponse};
+use crate::response::{ServerCode, ServerResponse};
 use serde::{
     de::{self, MapAccess, Visitor},
     Deserialize,
diff --git a/rust-lib/flowy-observable/src/entities/subject.rs b/rust-lib/flowy-observable/src/entities/subject.rs
index d2b3b14211..89ed245db0 100644
--- a/rust-lib/flowy-observable/src/entities/subject.rs
+++ b/rust-lib/flowy-observable/src/entities/subject.rs
@@ -21,7 +21,7 @@ impl std::default::Default for ObservableSubject {
             category: "".to_string(),
             ty: 0,
             subject_id: "".to_string(),
-            subject_payload: None
+            subject_payload: None,
         }
     }
 }
diff --git a/rust-lib/flowy-observable/src/protobuf/mod.rs b/rust-lib/flowy-observable/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/flowy-observable/src/protobuf/mod.rs
+++ b/rust-lib/flowy-observable/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/flowy-observable/src/protobuf/model/mod.rs b/rust-lib/flowy-observable/src/protobuf/model/mod.rs
index ce50dd797d..41671a628b 100644
--- a/rust-lib/flowy-observable/src/protobuf/model/mod.rs
+++ b/rust-lib/flowy-observable/src/protobuf/model/mod.rs
@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod subject; 
-pub use subject::*; 
+mod subject;
+pub use subject::*;
diff --git a/rust-lib/flowy-ot/src/server/mod.rs b/rust-lib/flowy-ot/src/server/mod.rs
index e69de29bb2..8b13789179 100644
--- a/rust-lib/flowy-ot/src/server/mod.rs
+++ b/rust-lib/flowy-ot/src/server/mod.rs
@@ -0,0 +1 @@
+
diff --git a/rust-lib/flowy-user/src/entities/sign_up.rs b/rust-lib/flowy-user/src/entities/sign_up.rs
index 83ba6b1ee5..caa1355c9f 100644
--- a/rust-lib/flowy-user/src/entities/sign_up.rs
+++ b/rust-lib/flowy-user/src/entities/sign_up.rs
@@ -57,9 +57,8 @@ pub struct SignUpParams {
 #[derive(ProtoBuf, Debug, Default)]
 pub struct SignUpResponse {
     #[pb(index = 1)]
-    pub is_success: bool,
-}
+    pub name: bool,
 
-impl SignUpResponse {
-    pub fn new(is_success: bool) -> Self { Self { is_success } }
+    #[pb(index = 2)]
+    pub email: String,
 }
diff --git a/rust-lib/flowy-user/src/protobuf/mod.rs b/rust-lib/flowy-user/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/flowy-user/src/protobuf/mod.rs
+++ b/rust-lib/flowy-user/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/flowy-user/src/protobuf/model/mod.rs b/rust-lib/flowy-user/src/protobuf/model/mod.rs
index 9d238d852e..319df1338e 100644
--- a/rust-lib/flowy-user/src/protobuf/model/mod.rs
+++ b/rust-lib/flowy-user/src/protobuf/model/mod.rs
@@ -1,22 +1,22 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod sign_up; 
-pub use sign_up::*; 
+mod sign_up;
+pub use sign_up::*;
 
-mod sign_in; 
-pub use sign_in::*; 
+mod sign_in;
+pub use sign_in::*;
 
-mod user_table; 
-pub use user_table::*; 
+mod user_table;
+pub use user_table::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod user_detail; 
-pub use user_detail::*; 
+mod user_detail;
+pub use user_detail::*;
 
-mod user_update; 
-pub use user_update::*; 
+mod user_update;
+pub use user_update::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
diff --git a/rust-lib/flowy-user/src/protobuf/model/sign_up.rs b/rust-lib/flowy-user/src/protobuf/model/sign_up.rs
index 010e8c4e9b..289900afdf 100644
--- a/rust-lib/flowy-user/src/protobuf/model/sign_up.rs
+++ b/rust-lib/flowy-user/src/protobuf/model/sign_up.rs
@@ -512,7 +512,8 @@ impl ::protobuf::reflect::ProtobufValue for SignUpParams {
 #[derive(PartialEq,Clone,Default)]
 pub struct SignUpResponse {
     // message fields
-    pub is_success: bool,
+    pub name: bool,
+    pub email: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -529,19 +530,45 @@ impl SignUpResponse {
         ::std::default::Default::default()
     }
 
-    // bool is_success = 1;
+    // bool name = 1;
 
 
-    pub fn get_is_success(&self) -> bool {
-        self.is_success
+    pub fn get_name(&self) -> bool {
+        self.name
     }
-    pub fn clear_is_success(&mut self) {
-        self.is_success = false;
+    pub fn clear_name(&mut self) {
+        self.name = false;
     }
 
     // Param is passed by value, moved
-    pub fn set_is_success(&mut self, v: bool) {
-        self.is_success = v;
+    pub fn set_name(&mut self, v: bool) {
+        self.name = v;
+    }
+
+    // string email = 2;
+
+
+    pub fn get_email(&self) -> &str {
+        &self.email
+    }
+    pub fn clear_email(&mut self) {
+        self.email.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_email(&mut self, v: ::std::string::String) {
+        self.email = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_email(&mut self) -> &mut ::std::string::String {
+        &mut self.email
+    }
+
+    // Take field
+    pub fn take_email(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.email, ::std::string::String::new())
     }
 }
 
@@ -559,7 +586,10 @@ impl ::protobuf::Message for SignUpResponse {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
                     let tmp = is.read_bool()?;
-                    self.is_success = tmp;
+                    self.name = tmp;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.email)?;
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -573,17 +603,23 @@ impl ::protobuf::Message for SignUpResponse {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if self.is_success != false {
+        if self.name != false {
             my_size += 2;
         }
+        if !self.email.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.email);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if self.is_success != false {
-            os.write_bool(1, self.is_success)?;
+        if self.name != false {
+            os.write_bool(1, self.name)?;
+        }
+        if !self.email.is_empty() {
+            os.write_string(2, &self.email)?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -624,9 +660,14 @@ impl ::protobuf::Message for SignUpResponse {
         descriptor.get(|| {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
-                "is_success",
-                |m: &SignUpResponse| { &m.is_success },
-                |m: &mut SignUpResponse| { &mut m.is_success },
+                "name",
+                |m: &SignUpResponse| { &m.name },
+                |m: &mut SignUpResponse| { &mut m.name },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "email",
+                |m: &SignUpResponse| { &m.email },
+                |m: &mut SignUpResponse| { &mut m.email },
             ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<SignUpResponse>(
                 "SignUpResponse",
@@ -644,7 +685,8 @@ impl ::protobuf::Message for SignUpResponse {
 
 impl ::protobuf::Clear for SignUpResponse {
     fn clear(&mut self) {
-        self.is_success = false;
+        self.name = false;
+        self.email.clear();
         self.unknown_fields.clear();
     }
 }
@@ -667,31 +709,34 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x08password\x18\x03\x20\x01(\tR\x08password\"T\n\x0cSignUpParams\x12\
     \x14\n\x05email\x18\x01\x20\x01(\tR\x05email\x12\x12\n\x04name\x18\x02\
     \x20\x01(\tR\x04name\x12\x1a\n\x08password\x18\x03\x20\x01(\tR\x08passwo\
-    rd\"/\n\x0eSignUpResponse\x12\x1d\n\nis_success\x18\x01\x20\x01(\x08R\ti\
-    sSuccessJ\xdb\x03\n\x06\x12\x04\0\0\x0e\x01\n\x08\n\x01\x0c\x12\x03\0\0\
-    \x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\
-    \x02\x08\x15\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x15\n\x0c\n\x05\x04\
-    \0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\
-    \x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x13\x14\n\x0b\n\x04\x04\
-    \0\x02\x01\x12\x03\x04\x04\x14\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\x0f\n\x0c\n\x05\x04\
-    \0\x02\x01\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\
-    \x04\x18\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\
-    \0\x02\x02\x01\x12\x03\x05\x0b\x13\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\
-    \x05\x16\x17\n\n\n\x02\x04\x01\x12\x04\x07\0\x0b\x01\n\n\n\x03\x04\x01\
-    \x01\x12\x03\x07\x08\x14\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x08\x04\x15\n\
-    \x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\0\
-    \x01\x12\x03\x08\x0b\x10\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x08\x13\
-    \x14\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x14\n\x0c\n\x05\x04\x01\
-    \x02\x01\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\t\
-    \x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x12\x13\n\x0b\n\x04\
-    \x04\x01\x02\x02\x12\x03\n\x04\x18\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\
-    \x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\n\x0b\x13\n\x0c\n\
-    \x05\x04\x01\x02\x02\x03\x12\x03\n\x16\x17\n\n\n\x02\x04\x02\x12\x04\x0c\
-    \0\x0e\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0c\x08\x16\n\x0b\n\x04\x04\x02\
-    \x02\0\x12\x03\r\x04\x18\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\r\x04\x08\
-    \n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\r\t\x13\n\x0c\n\x05\x04\x02\x02\0\
-    \x03\x12\x03\r\x16\x17b\x06proto3\
+    rd\":\n\x0eSignUpResponse\x12\x12\n\x04name\x18\x01\x20\x01(\x08R\x04nam\
+    e\x12\x14\n\x05email\x18\x02\x20\x01(\tR\x05emailJ\x92\x04\n\x06\x12\x04\
+    \0\0\x0f\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\
+    \0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x15\n\x0b\n\x04\x04\0\x02\
+    \0\x12\x03\x03\x04\x15\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\
+    \x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x10\n\x0c\n\x05\x04\0\x02\0\
+    \x03\x12\x03\x03\x13\x14\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\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\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\
+    \x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x18\n\x0c\n\x05\x04\0\x02\
+    \x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\
+    \x13\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x16\x17\n\n\n\x02\x04\x01\
+    \x12\x04\x07\0\x0b\x01\n\n\n\x03\x04\x01\x01\x12\x03\x07\x08\x14\n\x0b\n\
+    \x04\x04\x01\x02\0\x12\x03\x08\x04\x15\n\x0c\n\x05\x04\x01\x02\0\x05\x12\
+    \x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x08\x0b\x10\n\x0c\n\
+    \x05\x04\x01\x02\0\x03\x12\x03\x08\x13\x14\n\x0b\n\x04\x04\x01\x02\x01\
+    \x12\x03\t\x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\t\x04\n\n\x0c\
+    \n\x05\x04\x01\x02\x01\x01\x12\x03\t\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\
+    \x03\x12\x03\t\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\n\x04\x18\n\
+    \x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\
+    \x02\x01\x12\x03\n\x0b\x13\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\n\x16\
+    \x17\n\n\n\x02\x04\x02\x12\x04\x0c\0\x0f\x01\n\n\n\x03\x04\x02\x01\x12\
+    \x03\x0c\x08\x16\n\x0b\n\x04\x04\x02\x02\0\x12\x03\r\x04\x12\n\x0c\n\x05\
+    \x04\x02\x02\0\x05\x12\x03\r\x04\x08\n\x0c\n\x05\x04\x02\x02\0\x01\x12\
+    \x03\r\t\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\r\x10\x11\n\x0b\n\x04\
+    \x04\x02\x02\x01\x12\x03\x0e\x04\x15\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\
+    \x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x0e\x0b\x10\n\x0c\
+    \n\x05\x04\x02\x02\x01\x03\x12\x03\x0e\x13\x14b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
diff --git a/rust-lib/flowy-user/src/protobuf/proto/sign_up.proto b/rust-lib/flowy-user/src/protobuf/proto/sign_up.proto
index f6a7666970..0f54b163ca 100644
--- a/rust-lib/flowy-user/src/protobuf/proto/sign_up.proto
+++ b/rust-lib/flowy-user/src/protobuf/proto/sign_up.proto
@@ -11,5 +11,6 @@ message SignUpParams {
     string password = 3;
 }
 message SignUpResponse {
-    bool is_success = 1;
+    bool name = 1;
+    string email = 2;
 }
diff --git a/rust-lib/flowy-workspace/src/protobuf/mod.rs b/rust-lib/flowy-workspace/src/protobuf/mod.rs
index 2480f62fbe..8177ff8614 100644
--- a/rust-lib/flowy-workspace/src/protobuf/mod.rs
+++ b/rust-lib/flowy-workspace/src/protobuf/mod.rs
@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        
\ No newline at end of file
diff --git a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs
index 3aaff47db2..d1466cf304 100644
--- a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs
+++ b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs
@@ -1,49 +1,49 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod view_update; 
-pub use view_update::*; 
+mod view_update;
+pub use view_update::*;
 
-mod view_delete; 
-pub use view_delete::*; 
+mod view_delete;
+pub use view_delete::*;
 
-mod app_query; 
-pub use app_query::*; 
+mod app_query;
+pub use app_query::*;
 
-mod workspace_delete; 
-pub use workspace_delete::*; 
+mod workspace_delete;
+pub use workspace_delete::*;
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod workspace_update; 
-pub use workspace_update::*; 
+mod workspace_update;
+pub use workspace_update::*;
 
-mod app_create; 
-pub use app_create::*; 
+mod app_create;
+pub use app_create::*;
 
-mod workspace_query; 
-pub use workspace_query::*; 
+mod workspace_query;
+pub use workspace_query::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod view_create; 
-pub use view_create::*; 
+mod view_create;
+pub use view_create::*;
 
-mod workspace_user_detail; 
-pub use workspace_user_detail::*; 
+mod workspace_user_detail;
+pub use workspace_user_detail::*;
 
-mod workspace_create; 
-pub use workspace_create::*; 
+mod workspace_create;
+pub use workspace_create::*;
 
-mod app_update; 
-pub use app_update::*; 
+mod app_update;
+pub use app_update::*;
 
-mod view_query; 
-pub use view_query::*; 
+mod view_query;
+pub use view_query::*;
 
-mod app_delete; 
-pub use app_delete::*; 
+mod app_delete;
+pub use app_delete::*;
diff --git a/rust-lib/flowy-workspace/src/services/database.rs b/rust-lib/flowy-workspace/src/services/database.rs
index e69de29bb2..8b13789179 100644
--- a/rust-lib/flowy-workspace/src/services/database.rs
+++ b/rust-lib/flowy-workspace/src/services/database.rs
@@ -0,0 +1 @@
+