From 49e5f384061877692fbb987de154f83ccac7d2aa Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 21 Aug 2021 17:17:54 +0800 Subject: [PATCH] consume reqwest status code --- .../protobuf/flowy-user/errors.pbenum.dart | 34 +++- .../protobuf/flowy-user/errors.pbjson.dart | 23 ++- backend/src/routers/helper.rs | 20 +- backend/src/startup.rs | 10 +- backend/src/user_service/auth.rs | 8 +- backend/src/ws_service/entities/connect.rs | 6 +- backend/src/ws_service/ws_server.rs | 6 +- rust-lib/dart-ffi/Cargo.toml | 8 +- .../src/derive_cache/derive_cache.rs | 1 + rust-lib/flowy-infra/src/errors/builder.rs | 46 +++++ rust-lib/flowy-infra/src/errors/mod.rs | 3 + rust-lib/flowy-net/Cargo.toml | 5 +- rust-lib/flowy-net/src/errors.rs | 40 ---- rust-lib/flowy-net/src/errors/errors.rs | 45 +++++ rust-lib/flowy-net/src/errors/mod.rs | 3 + rust-lib/flowy-net/src/request/request.rs | 31 ++-- rust-lib/flowy-net/src/response/response.rs | 101 +++++++++- .../flowy-net/src/response/response_http.rs | 29 +-- .../src/entities/parser/user_email.rs | 7 +- .../src/entities/parser/user_name.rs | 17 +- .../src/entities/parser/user_password.rs | 12 +- rust-lib/flowy-user/src/entities/sign_in.rs | 10 +- rust-lib/flowy-user/src/entities/sign_up.rs | 17 +- .../flowy-user/src/entities/user_update.rs | 14 +- rust-lib/flowy-user/src/errors.rs | 49 +++-- .../flowy-user/src/protobuf/model/errors.rs | 175 +++++++++++------- .../src/protobuf/proto/errors.proto | 21 ++- rust-lib/flowy-user/tests/server/main.rs | 1 + rust-lib/flowy-user/tests/server/user_test.rs | 13 ++ 29 files changed, 501 insertions(+), 254 deletions(-) create mode 100644 rust-lib/flowy-infra/src/errors/builder.rs create mode 100644 rust-lib/flowy-infra/src/errors/mod.rs delete mode 100644 rust-lib/flowy-net/src/errors.rs create mode 100644 rust-lib/flowy-net/src/errors/errors.rs create mode 100644 rust-lib/flowy-net/src/errors/mod.rs create mode 100644 rust-lib/flowy-user/tests/server/main.rs create mode 100644 rust-lib/flowy-user/tests/server/user_test.rs diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart index 5890b6f76f..27ccefcd50 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart @@ -20,13 +20,20 @@ class UserErrCode extends $pb.ProtobufEnum { static const UserErrCode UserNotLoginYet = UserErrCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet'); static const UserErrCode ReadCurrentIdFailed = UserErrCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadCurrentIdFailed'); static const UserErrCode WriteCurrentIdFailed = UserErrCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WriteCurrentIdFailed'); - static const UserErrCode EmailInvalid = UserErrCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailInvalid'); - static const UserErrCode PasswordInvalid = UserErrCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordInvalid'); - static const UserErrCode UserNameInvalid = UserErrCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameInvalid'); - static const UserErrCode UserWorkspaceInvalid = UserErrCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid'); - static const UserErrCode UserIdInvalid = UserErrCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); - static const UserErrCode CreateDefaultWorkspaceFailed = UserErrCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed'); - static const UserErrCode DefaultWorkspaceAlreadyExist = UserErrCode._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DefaultWorkspaceAlreadyExist'); + static const UserErrCode EmailIsEmpty = UserErrCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailIsEmpty'); + static const UserErrCode EmailFormatInvalid = UserErrCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailFormatInvalid'); + static const UserErrCode EmailAlreadyExists = UserErrCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailAlreadyExists'); + static const UserErrCode PasswordIsEmpty = UserErrCode._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordIsEmpty'); + static const UserErrCode PasswordTooLong = UserErrCode._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordTooLong'); + static const UserErrCode PasswordContainsForbidCharacters = UserErrCode._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordContainsForbidCharacters'); + static const UserErrCode PasswordFormatInvalid = UserErrCode._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordFormatInvalid'); + static const UserErrCode UserNameTooLong = UserErrCode._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameTooLong'); + static const UserErrCode UserNameContainsForbiddenCharacters = UserErrCode._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameContainsForbiddenCharacters'); + static const UserErrCode UserNameIsEmpty = UserErrCode._(42, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameIsEmpty'); + static const UserErrCode UserWorkspaceInvalid = UserErrCode._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid'); + static const UserErrCode UserIdInvalid = UserErrCode._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); + static const UserErrCode CreateDefaultWorkspaceFailed = UserErrCode._(52, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed'); + static const UserErrCode DefaultWorkspaceAlreadyExist = UserErrCode._(53, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DefaultWorkspaceAlreadyExist'); static const UserErrCode NetworkError = UserErrCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NetworkError'); static const $core.List values = [ @@ -40,9 +47,16 @@ class UserErrCode extends $pb.ProtobufEnum { UserNotLoginYet, ReadCurrentIdFailed, WriteCurrentIdFailed, - EmailInvalid, - PasswordInvalid, - UserNameInvalid, + EmailIsEmpty, + EmailFormatInvalid, + EmailAlreadyExists, + PasswordIsEmpty, + PasswordTooLong, + PasswordContainsForbidCharacters, + PasswordFormatInvalid, + UserNameTooLong, + UserNameContainsForbiddenCharacters, + UserNameIsEmpty, UserWorkspaceInvalid, UserIdInvalid, CreateDefaultWorkspaceFailed, diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart index 53f0264580..517a837d20 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart @@ -22,19 +22,26 @@ const UserErrCode$json = const { const {'1': 'UserNotLoginYet', '2': 10}, const {'1': 'ReadCurrentIdFailed', '2': 11}, const {'1': 'WriteCurrentIdFailed', '2': 12}, - const {'1': 'EmailInvalid', '2': 20}, - const {'1': 'PasswordInvalid', '2': 21}, - const {'1': 'UserNameInvalid', '2': 22}, - const {'1': 'UserWorkspaceInvalid', '2': 23}, - const {'1': 'UserIdInvalid', '2': 24}, - const {'1': 'CreateDefaultWorkspaceFailed', '2': 25}, - const {'1': 'DefaultWorkspaceAlreadyExist', '2': 26}, + const {'1': 'EmailIsEmpty', '2': 20}, + const {'1': 'EmailFormatInvalid', '2': 21}, + const {'1': 'EmailAlreadyExists', '2': 22}, + const {'1': 'PasswordIsEmpty', '2': 30}, + const {'1': 'PasswordTooLong', '2': 31}, + const {'1': 'PasswordContainsForbidCharacters', '2': 32}, + const {'1': 'PasswordFormatInvalid', '2': 33}, + const {'1': 'UserNameTooLong', '2': 40}, + const {'1': 'UserNameContainsForbiddenCharacters', '2': 41}, + const {'1': 'UserNameIsEmpty', '2': 42}, + const {'1': 'UserWorkspaceInvalid', '2': 50}, + const {'1': 'UserIdInvalid', '2': 51}, + const {'1': 'CreateDefaultWorkspaceFailed', '2': 52}, + const {'1': 'DefaultWorkspaceAlreadyExist', '2': 53}, const {'1': 'NetworkError', '2': 100}, ], }; /// Descriptor for `UserErrCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List userErrCodeDescriptor = $convert.base64Decode('CgtVc2VyRXJyQ29kZRILCgdVbmtub3duEAASGgoWVXNlckRhdGFiYXNlSW5pdEZhaWxlZBABEhsKF1VzZXJEYXRhYmFzZVdyaXRlTG9ja2VkEAISGgoWVXNlckRhdGFiYXNlUmVhZExvY2tlZBADEhsKF1VzZXJEYXRhYmFzZURpZE5vdE1hdGNoEAQSHQoZVXNlckRhdGFiYXNlSW50ZXJuYWxFcnJvchAFEhQKEFNxbEludGVybmFsRXJyb3IQBhITCg9Vc2VyTm90TG9naW5ZZXQQChIXChNSZWFkQ3VycmVudElkRmFpbGVkEAsSGAoUV3JpdGVDdXJyZW50SWRGYWlsZWQQDBIQCgxFbWFpbEludmFsaWQQFBITCg9QYXNzd29yZEludmFsaWQQFRITCg9Vc2VyTmFtZUludmFsaWQQFhIYChRVc2VyV29ya3NwYWNlSW52YWxpZBAXEhEKDVVzZXJJZEludmFsaWQQGBIgChxDcmVhdGVEZWZhdWx0V29ya3NwYWNlRmFpbGVkEBkSIAocRGVmYXVsdFdvcmtzcGFjZUFscmVhZHlFeGlzdBAaEhAKDE5ldHdvcmtFcnJvchBk'); +final $typed_data.Uint8List userErrCodeDescriptor = $convert.base64Decode('CgtVc2VyRXJyQ29kZRILCgdVbmtub3duEAASGgoWVXNlckRhdGFiYXNlSW5pdEZhaWxlZBABEhsKF1VzZXJEYXRhYmFzZVdyaXRlTG9ja2VkEAISGgoWVXNlckRhdGFiYXNlUmVhZExvY2tlZBADEhsKF1VzZXJEYXRhYmFzZURpZE5vdE1hdGNoEAQSHQoZVXNlckRhdGFiYXNlSW50ZXJuYWxFcnJvchAFEhQKEFNxbEludGVybmFsRXJyb3IQBhITCg9Vc2VyTm90TG9naW5ZZXQQChIXChNSZWFkQ3VycmVudElkRmFpbGVkEAsSGAoUV3JpdGVDdXJyZW50SWRGYWlsZWQQDBIQCgxFbWFpbElzRW1wdHkQFBIWChJFbWFpbEZvcm1hdEludmFsaWQQFRIWChJFbWFpbEFscmVhZHlFeGlzdHMQFhITCg9QYXNzd29yZElzRW1wdHkQHhITCg9QYXNzd29yZFRvb0xvbmcQHxIkCiBQYXNzd29yZENvbnRhaW5zRm9yYmlkQ2hhcmFjdGVycxAgEhkKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBAhEhMKD1VzZXJOYW1lVG9vTG9uZxAoEicKI1VzZXJOYW1lQ29udGFpbnNGb3JiaWRkZW5DaGFyYWN0ZXJzECkSEwoPVXNlck5hbWVJc0VtcHR5ECoSGAoUVXNlcldvcmtzcGFjZUludmFsaWQQMhIRCg1Vc2VySWRJbnZhbGlkEDMSIAocQ3JlYXRlRGVmYXVsdFdvcmtzcGFjZUZhaWxlZBA0EiAKHERlZmF1bHRXb3Jrc3BhY2VBbHJlYWR5RXhpc3QQNRIQCgxOZXR3b3JrRXJyb3IQZA=='); @$core.Deprecated('Use userErrorDescriptor instead') const UserError$json = const { '1': 'UserError', diff --git a/backend/src/routers/helper.rs b/backend/src/routers/helper.rs index 6b90af0382..977dfd2ec7 100644 --- a/backend/src/routers/helper.rs +++ b/backend/src/routers/helper.rs @@ -1,15 +1,15 @@ use crate::config::MAX_PAYLOAD_SIZE; use actix_web::web; -use flowy_net::{errors::NetworkError, response::*}; +use flowy_net::response::*; use futures::StreamExt; use protobuf::{Message, ProtobufResult}; -pub async fn parse_from_payload(payload: web::Payload) -> Result { +pub async fn parse_from_payload(payload: web::Payload) -> Result { let bytes = poll_payload(payload).await?; parse_from_bytes(&bytes) } -pub fn parse_from_bytes(bytes: &[u8]) -> Result { +pub fn parse_from_bytes(bytes: &[u8]) -> Result { let result: ProtobufResult = Message::parse_from_bytes(&bytes); match result { Ok(data) => Ok(data), @@ -17,13 +17,19 @@ pub fn parse_from_bytes(bytes: &[u8]) -> Result { } } -pub async fn poll_payload(mut payload: web::Payload) -> Result { +pub async fn poll_payload(mut payload: web::Payload) -> Result { let mut body = web::BytesMut::new(); while let Some(chunk) = payload.next().await { - let chunk = chunk.map_err(|e| NetworkError::InternalError(format!("{:?}", e)))?; + let chunk = chunk.map_err(|e| ServerError { + code: ServerCode::InternalError, + msg: format!("{:?}", e), + })?; + if (body.len() + chunk.len()) > MAX_PAYLOAD_SIZE { - let resp = FlowyResponse::from_msg("Payload overflow", ServerCode::PayloadOverflow); - return Err(NetworkError::BadRequest(resp)); + return Err(ServerError { + code: ServerCode::PayloadOverflow, + msg: "Payload overflow".to_string(), + }); } body.extend_from_slice(&chunk); } diff --git a/backend/src/startup.rs b/backend/src/startup.rs index 85c55fb961..12438c0990 100644 --- a/backend/src/startup.rs +++ b/backend/src/startup.rs @@ -6,7 +6,7 @@ use crate::{ ws_service::WSServer, }; use actix::Actor; -use actix_web::{dev::Server, middleware, web, App, HttpServer, Scope}; +use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer, Scope}; use sqlx::PgPool; use std::{net::TcpListener, sync::Arc}; @@ -14,12 +14,12 @@ pub fn run(app_ctx: Arc, listener: TcpListener) -> Result) -> Self { Self { db_pool } } - pub fn sign_up(&self, params: SignUpParams) -> Result { + pub fn sign_up(&self, params: SignUpParams) -> Result { // email exist? // generate user id - // - unimplemented!() } - pub fn is_email_exist(&self, email: &str) -> bool {} + pub fn is_email_exist(&self, email: &str) -> bool { true } } diff --git a/backend/src/ws_service/entities/connect.rs b/backend/src/ws_service/entities/connect.rs index fd7404bee9..20336b1bd3 100644 --- a/backend/src/ws_service/entities/connect.rs +++ b/backend/src/ws_service/entities/connect.rs @@ -1,6 +1,6 @@ use crate::ws_service::ClientMessage; use actix::{Message, Recipient}; -use flowy_net::errors::NetworkError; +use flowy_net::response::ServerError; use serde::{Deserialize, Serialize}; use std::fmt::Formatter; @@ -37,14 +37,14 @@ impl std::fmt::Display for SessionId { } #[derive(Debug, Message, Clone)] -#[rtype(result = "Result<(), NetworkError>")] +#[rtype(result = "Result<(), ServerError>")] pub struct Connect { pub socket: Socket, pub sid: SessionId, } #[derive(Debug, Message, Clone)] -#[rtype(result = "Result<(), NetworkError>")] +#[rtype(result = "Result<(), ServerError>")] pub struct Disconnect { pub sid: SessionId, } diff --git a/backend/src/ws_service/ws_server.rs b/backend/src/ws_service/ws_server.rs index e223d167f3..091b19ea17 100644 --- a/backend/src/ws_service/ws_server.rs +++ b/backend/src/ws_service/ws_server.rs @@ -4,7 +4,7 @@ use crate::ws_service::{ }; use actix::{Actor, Context, Handler}; use dashmap::DashMap; -use flowy_net::errors::NetworkError; +use flowy_net::response::ServerError; pub struct WSServer { sessions: DashMap, @@ -26,7 +26,7 @@ impl Actor for WSServer { } impl Handler for WSServer { - type Result = Result<(), NetworkError>; + type Result = Result<(), ServerError>; fn handle(&mut self, msg: Connect, _ctx: &mut Context) -> Self::Result { let session: Session = msg.into(); self.sessions.insert(session.id.clone(), session); @@ -36,7 +36,7 @@ impl Handler for WSServer { } impl Handler for WSServer { - type Result = Result<(), NetworkError>; + type Result = Result<(), ServerError>; fn handle(&mut self, msg: Disconnect, _: &mut Context) -> Self::Result { self.sessions.remove(&msg.sid); Ok(()) diff --git a/rust-lib/dart-ffi/Cargo.toml b/rust-lib/dart-ffi/Cargo.toml index 3132ea54aa..b29f4558cf 100644 --- a/rust-lib/dart-ffi/Cargo.toml +++ b/rust-lib/dart-ffi/Cargo.toml @@ -7,11 +7,11 @@ edition = "2018" [lib] name = "dart_ffi" # this value will change depending on the target os -# for iOS it would be `rlib` -# for Macos it would be `rlib` +# for iOS it would be `cdylib` +# for Macos it would be `cdylib` # for android it would be `c-dylib` -# default rlib -crate-type = ["rlib"] +# default cdylib +crate-type = ["cdylib"] [dependencies] 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 d0ebd87160..6bcea530cb 100644 --- a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -64,6 +64,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "EditorEvent" | "DocErrorCode" | "FFIStatusCode" + | "UserServerError" | "UserStatus" | "UserEvent" | "UserErrCode" diff --git a/rust-lib/flowy-infra/src/errors/builder.rs b/rust-lib/flowy-infra/src/errors/builder.rs new file mode 100644 index 0000000000..834764d5bb --- /dev/null +++ b/rust-lib/flowy-infra/src/errors/builder.rs @@ -0,0 +1,46 @@ +use std::{fmt::Debug, marker::PhantomData}; + +pub trait Build { + fn build(code: C, msg: String) -> Self; +} + +pub struct Builder { + pub code: C, + pub msg: Option, + phantom: PhantomData, +} + +impl Builder +where + C: Debug, + O: Build + Build, +{ + pub fn new(code: C) -> Self { + Builder { + code, + msg: None, + phantom: PhantomData, + } + } + + pub fn msg(mut self, msg: M) -> Self + where + M: Into, + { + self.msg = Some(msg.into()); + self + } + + pub fn error(mut self, err: Err) -> Self + where + Err: std::fmt::Debug, + { + self.msg = Some(format!("{:?}", err)); + self + } + + pub fn build(mut self) -> O { + let msg = self.msg.take().unwrap_or("".to_owned()); + O::build(self.code, msg) + } +} diff --git a/rust-lib/flowy-infra/src/errors/mod.rs b/rust-lib/flowy-infra/src/errors/mod.rs new file mode 100644 index 0000000000..d01becf712 --- /dev/null +++ b/rust-lib/flowy-infra/src/errors/mod.rs @@ -0,0 +1,3 @@ +pub mod builder; + +pub use builder::*; diff --git a/rust-lib/flowy-net/Cargo.toml b/rust-lib/flowy-net/Cargo.toml index ed43e3e68e..b236a46356 100644 --- a/rust-lib/flowy-net/Cargo.toml +++ b/rust-lib/flowy-net/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] reqwest = "0.11" +hyper = "0.14" protobuf = {version = "2.18.0"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -17,8 +18,10 @@ log = "0.4" bytes = "1.0" lazy_static = "1.4.0" tokio = { version = "1", features = ["full"] } - actix-web = {version = "4.0.0-beta.8", optional = true} +derive_more = {version = "0.99", features = ["display"]} +flowy-derive = { path = "../flowy-derive" } + [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 deleted file mode 100644 index b419361200..0000000000 --- a/rust-lib/flowy-net/src/errors.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::response::FlowyResponse; -use protobuf::ProtobufError; -use std::fmt::{Formatter, Write}; - -#[derive(Debug)] -pub enum NetworkError { - InternalError(String), - ProtobufError(ProtobufError), - BadRequest(FlowyResponse), - Unauthorized, -} - -impl std::fmt::Display for NetworkError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - NetworkError::InternalError(_) => f.write_str("Internal Server Error"), - NetworkError::ProtobufError(err) => f.write_str(&format!("protobuf error: {}", err)), - NetworkError::BadRequest(request) => { - let msg = format!("Bad Request: {:?}", request); - f.write_str(&msg) - }, - NetworkError::Unauthorized => f.write_str("Unauthorized"), - } - } -} - -impl std::convert::From for NetworkError { - fn from(err: ProtobufError) -> Self { NetworkError::ProtobufError(err) } -} - -impl std::convert::From for NetworkError { - fn from(error: reqwest::Error) -> Self { - let msg = format!("{:?}", error); - NetworkError::InternalError(msg) - } -} - -impl std::convert::From for NetworkError { - fn from(error: String) -> Self { NetworkError::InternalError(error) } -} diff --git a/rust-lib/flowy-net/src/errors/errors.rs b/rust-lib/flowy-net/src/errors/errors.rs new file mode 100644 index 0000000000..6a7b431a7f --- /dev/null +++ b/rust-lib/flowy-net/src/errors/errors.rs @@ -0,0 +1,45 @@ +use crate::response::FlowyResponse; +use protobuf::ProtobufError; +use std::fmt::{Formatter, Write}; + +// #[derive(Debug)] +// pub struct ServerError { +// code: ErrorCode +// } +// +// pub enum ErrorCode { +// InternalError(String), +// ProtobufError(ProtobufError), +// BadRequest(FlowyResponse), +// Unauthorized, +// } +// +// +// impl std::fmt::Display for ErrorCode { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// match self { +// ErrorCode::InternalError(_) => f.write_str("Internal Server +// Error"), ErrorCode::ProtobufError(err) => +// f.write_str(&format!("protobuf error: {}", err)), +// ErrorCode::BadRequest(request) => { let msg = format!("Bad +// Request: {:?}", request); f.write_str(&msg) +// }, +// ErrorCode::Unauthorized => f.write_str("Unauthorized"), +// } +// } +// } + +// impl std::convert::From for ServerCode { +// fn from(err: ProtobufError) -> Self { ServerCode::ProtobufError(err) } +// } +// +// impl std::convert::From for ServerError { +// fn from(error: reqwest::Error) -> Self { +// let msg = format!("{:?}", error); +// ServerError::InternalError(msg) +// } +// } +// +// impl std::convert::From for ServerError { +// fn from(error: String) -> Self { ServerError::InternalError(error) } +// } diff --git a/rust-lib/flowy-net/src/errors/mod.rs b/rust-lib/flowy-net/src/errors/mod.rs new file mode 100644 index 0000000000..852f5c0f5e --- /dev/null +++ b/rust-lib/flowy-net/src/errors/mod.rs @@ -0,0 +1,3 @@ +mod errors; + +pub use errors::*; diff --git a/rust-lib/flowy-net/src/request/request.rs b/rust-lib/flowy-net/src/request/request.rs index 85ac9b65d2..5c3532f5e4 100644 --- a/rust-lib/flowy-net/src/request/request.rs +++ b/rust-lib/flowy-net/src/request/request.rs @@ -1,4 +1,4 @@ -use crate::{errors::NetworkError, future::ResultFuture}; +use crate::{future::ResultFuture, response::ServerError}; use bytes::Bytes; use protobuf::{Message, ProtobufError}; use reqwest::{Client, Error, Response}; @@ -6,7 +6,9 @@ use std::{ convert::{TryFrom, TryInto}, time::Duration, }; +use hyper::{StatusCode, http}; use tokio::sync::{oneshot, oneshot::error::RecvError}; +use crate::response::ServerCode; // pub async fn http_post(url: &str, data: T1) -> ResultFuture where @@ -17,7 +19,7 @@ use tokio::sync::{oneshot, oneshot::error::RecvError}; // ResultFuture::new(async move { post(url, data).await }) // } -pub async fn http_post(url: &str, data: T1) -> Result +pub async fn http_post(url: &str, data: T1) -> Result where T1: TryInto, T2: TryFrom, @@ -32,20 +34,21 @@ where tx.send(response); }); - match rx.await { - Ok(response) => { - let response = response?; - let response_bytes = response.bytes().await?; - let data = T2::try_from(response_bytes)?; - Ok(data) - }, - Err(e) => { - unimplemented!() - }, + let response = rx.await??; + if response.status() == http::StatusCode::OK { + let response_bytes = response.bytes().await?; + let data = T2::try_from(response_bytes)?; + Ok(data) + + } else { + Err(ServerError { + code: ServerCode::InternalError, + msg: format!("{:?}", response), + }) } } -async fn parse_response(response: Response) -> Result +async fn parse_response(response: Response) -> Result where T: Message, { @@ -53,7 +56,7 @@ where parse_bytes(bytes) } -fn parse_bytes(bytes: Bytes) -> Result +fn parse_bytes(bytes: Bytes) -> Result where T: Message, { diff --git a/rust-lib/flowy-net/src/response/response.rs b/rust-lib/flowy-net/src/response/response.rs index a44709bc0c..7b2b7108ab 100644 --- a/rust-lib/flowy-net/src/response/response.rs +++ b/rust-lib/flowy-net/src/response/response.rs @@ -1,8 +1,32 @@ -use serde::Serialize; - +use serde::{Serialize, __private::Formatter}; use serde_repr::*; +use std::{error::Error, fmt}; +use tokio::sync::oneshot::error::RecvError; -#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)] +#[derive(Debug)] +pub struct ServerError { + pub code: ServerCode, + pub msg: String, +} + +impl std::fmt::Display for ServerError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let msg = format!("{:?}:{}", self.code, self.msg); + f.write_str(&msg) + } +} + +impl std::convert::From<&ServerError> for FlowyResponse { + fn from(error: &ServerError) -> Self { + FlowyResponse { + msg: error.msg.clone(), + data: None, + code: error.code.clone(), + } + } +} + +#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)] #[repr(u16)] pub enum ServerCode { Success = 0, @@ -12,6 +36,11 @@ pub enum ServerCode { PayloadOverflow = 4, PayloadSerdeFail = 5, ProtobufError = 6, + SerdeError = 7, + ConnectRefused = 8, + ConnectTimeout = 9, + ConnectClose = 10, + ConnectCancel = 11, } #[derive(Debug, Serialize)] @@ -42,3 +71,69 @@ impl FlowyResponse { Self::new(Some("".to_owned()), msg, code) } } + +impl std::convert::From for ServerError { + fn from(err: protobuf::ProtobufError) -> Self { + ServerError { + code: ServerCode::ProtobufError, + msg: format!("{}", err), + } + } +} + +impl std::convert::From for ServerError { + fn from(error: RecvError) -> Self { + ServerError { + code: ServerCode::InternalError, + msg: format!("{:?}", error), + } + } +} + +impl std::convert::From for ServerError { + fn from(error: reqwest::Error) -> Self { + if error.is_timeout() { + return ServerError { + code: ServerCode::ConnectTimeout, + msg: format!("{}", error), + }; + } + + if error.is_request() { + let hyper_error: Option<&hyper::Error> = error.source().unwrap().downcast_ref(); + return match hyper_error { + None => ServerError { + code: ServerCode::ConnectRefused, + msg: format!("{:?}", error), + }, + Some(hyper_error) => { + let mut code = ServerCode::InternalError; + let msg = format!("{}", error); + if hyper_error.is_closed() { + code = ServerCode::ConnectClose; + } + + if hyper_error.is_connect() { + code = ServerCode::ConnectRefused; + } + + if hyper_error.is_canceled() { + code = ServerCode::ConnectCancel; + } + + if hyper_error.is_timeout() { + + } + + ServerError { code, msg } + }, + }; + } + + let msg = format!("{:?}", error); + ServerError { + code: ServerCode::ProtobufError, + msg, + } + } +} diff --git a/rust-lib/flowy-net/src/response/response_http.rs b/rust-lib/flowy-net/src/response/response_http.rs index ecc962384a..8c33bd6e11 100644 --- a/rust-lib/flowy-net/src/response/response_http.rs +++ b/rust-lib/flowy-net/src/response/response_http.rs @@ -1,28 +1,15 @@ -use crate::{errors::NetworkError, response::*}; +use crate::response::*; use actix_web::{body::Body, error::ResponseError, BaseHttpResponse, HttpResponse}; use serde::Serialize; -impl NetworkError { +impl ServerError { fn http_response(&self) -> HttpResponse { - match self { - NetworkError::InternalError(msg) => { - let resp = FlowyResponse::from_msg(&msg, ServerCode::InternalError); - HttpResponse::InternalServerError().json(resp) - }, - NetworkError::ProtobufError(err) => { - let resp = FlowyResponse::from_msg(&format!("{}", err), ServerCode::ProtobufError); - HttpResponse::InternalServerError().json(resp) - }, - NetworkError::BadRequest(ref resp) => HttpResponse::BadRequest().json(resp), - NetworkError::Unauthorized => { - let resp = FlowyResponse::from_msg("Unauthorized", ServerCode::Unauthorized); - HttpResponse::Unauthorized().json(resp) - }, - } + let resp: FlowyResponse = self.into(); + HttpResponse::Ok().json(resp) } } -impl ResponseError for NetworkError { +impl ResponseError for ServerError { fn error_response(&self) -> HttpResponse { self.http_response().into() } } @@ -32,7 +19,11 @@ impl std::convert::Into for FlowyResponse { Ok(body) => HttpResponse::Ok().body(Body::from(body)), Err(e) => { let msg = format!("Serial error: {:?}", e); - NetworkError::InternalError(msg).error_response() + ServerError { + code: ServerCode::SerdeError, + msg, + } + .error_response() }, } } diff --git a/rust-lib/flowy-user/src/entities/parser/user_email.rs b/rust-lib/flowy-user/src/entities/parser/user_email.rs index c75d438a30..062d18091d 100644 --- a/rust-lib/flowy-user/src/entities/parser/user_email.rs +++ b/rust-lib/flowy-user/src/entities/parser/user_email.rs @@ -1,18 +1,19 @@ +use crate::errors::UserErrCode; use validator::validate_email; #[derive(Debug)] pub struct UserEmail(pub String); impl UserEmail { - pub fn parse(s: String) -> Result { + pub fn parse(s: String) -> Result { if s.trim().is_empty() { - return Err(format!("Email can not be empty or whitespace")); + return Err(UserErrCode::EmailIsEmpty); } if validate_email(&s) { Ok(Self(s)) } else { - Err(format!("{} is not a valid email.", s)) + Err(UserErrCode::EmailFormatInvalid) } } } diff --git a/rust-lib/flowy-user/src/entities/parser/user_name.rs b/rust-lib/flowy-user/src/entities/parser/user_name.rs index 01970de4d0..6ac6dc507b 100644 --- a/rust-lib/flowy-user/src/entities/parser/user_name.rs +++ b/rust-lib/flowy-user/src/entities/parser/user_name.rs @@ -1,11 +1,15 @@ +use crate::errors::UserErrCode; use unicode_segmentation::UnicodeSegmentation; #[derive(Debug)] pub struct UserName(pub String); impl UserName { - pub fn parse(s: String) -> Result { + pub fn parse(s: String) -> Result { let is_empty_or_whitespace = s.trim().is_empty(); + if is_empty_or_whitespace { + return Err(UserErrCode::UserNameIsEmpty); + } // A grapheme is defined by the Unicode standard as a "user-perceived" // character: `å` is a single grapheme, but it is composed of two characters // (`a` and `̊`). @@ -14,15 +18,18 @@ impl UserName { // `true` specifies that we want to use the extended grapheme definition set, // the recommended one. let is_too_long = s.graphemes(true).count() > 256; + if is_too_long { + return Err(UserErrCode::UserNameTooLong); + } let forbidden_characters = ['/', '(', ')', '"', '<', '>', '\\', '{', '}']; let contains_forbidden_characters = s.chars().any(|g| forbidden_characters.contains(&g)); - if is_empty_or_whitespace || is_too_long || contains_forbidden_characters { - Err(format!("{} is not a valid name.", s)) - } else { - Ok(Self(s)) + if contains_forbidden_characters { + return Err(UserErrCode::UserNameContainsForbiddenCharacters); } + + Ok(Self(s)) } } diff --git a/rust-lib/flowy-user/src/entities/parser/user_password.rs b/rust-lib/flowy-user/src/entities/parser/user_password.rs index 99e0695cc2..881d410c3b 100644 --- a/rust-lib/flowy-user/src/entities/parser/user_password.rs +++ b/rust-lib/flowy-user/src/entities/parser/user_password.rs @@ -1,27 +1,29 @@ +use crate::errors::UserErrCode; use fancy_regex::Regex; use lazy_static::lazy_static; use unicode_segmentation::UnicodeSegmentation; + #[derive(Debug)] pub struct UserPassword(pub String); impl UserPassword { - pub fn parse(s: String) -> Result { + pub fn parse(s: String) -> Result { if s.trim().is_empty() { - return Err(format!("Password can not be empty or whitespace.")); + return Err(UserErrCode::PasswordIsEmpty); } if s.graphemes(true).count() > 100 { - return Err(format!("Password too long.")); + return Err(UserErrCode::PasswordTooLong); } let forbidden_characters = ['/', '(', ')', '"', '<', '>', '\\', '{', '}']; let contains_forbidden_characters = s.chars().any(|g| forbidden_characters.contains(&g)); if contains_forbidden_characters { - return Err(format!("Password contains forbidden characters.")); + return Err(UserErrCode::PasswordContainsForbidCharacters); } if !validate_password(&s) { - return Err(format!("Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric")); + return Err(UserErrCode::PasswordFormatInvalid); } Ok(Self(s)) diff --git a/rust-lib/flowy-user/src/entities/sign_in.rs b/rust-lib/flowy-user/src/entities/sign_in.rs index ec9e3e49d7..a2c75f282d 100644 --- a/rust-lib/flowy-user/src/entities/sign_in.rs +++ b/rust-lib/flowy-user/src/entities/sign_in.rs @@ -36,13 +36,9 @@ impl TryInto for SignInRequest { type Error = UserError; fn try_into(self) -> Result { - let email = UserEmail::parse(self.email) - .map_err(|e| ErrorBuilder::new(UserErrCode::EmailInvalid).msg(e).build())?; - let password = UserPassword::parse(self.password).map_err(|e| { - ErrorBuilder::new(UserErrCode::PasswordInvalid) - .msg(e) - .build() - })?; + let email = UserEmail::parse(self.email).map_err(|e| ErrorBuilder::new(e).build())?; + let password = + UserPassword::parse(self.password).map_err(|e| ErrorBuilder::new(e).build())?; Ok(SignInParams { email: email.0, diff --git a/rust-lib/flowy-user/src/entities/sign_up.rs b/rust-lib/flowy-user/src/entities/sign_up.rs index 4ecd51f408..a1395c51c2 100644 --- a/rust-lib/flowy-user/src/entities/sign_up.rs +++ b/rust-lib/flowy-user/src/entities/sign_up.rs @@ -20,19 +20,10 @@ impl TryInto for SignUpRequest { type Error = UserError; fn try_into(self) -> Result { - let email = UserEmail::parse(self.email) - .map_err(|e| ErrorBuilder::new(UserErrCode::EmailInvalid).msg(e).build())?; - let password = UserPassword::parse(self.password).map_err(|e| { - ErrorBuilder::new(UserErrCode::PasswordInvalid) - .msg(e) - .build() - })?; - - let name = UserName::parse(self.name).map_err(|e| { - ErrorBuilder::new(UserErrCode::UserNameInvalid) - .msg(e) - .build() - })?; + let email = UserEmail::parse(self.email).map_err(|e| ErrorBuilder::new(e).build())?; + let password = + UserPassword::parse(self.password).map_err(|e| ErrorBuilder::new(e).build())?; + let name = UserName::parse(self.name).map_err(|e| ErrorBuilder::new(e).build())?; Ok(SignUpParams { email: email.0, diff --git a/rust-lib/flowy-user/src/entities/user_update.rs b/rust-lib/flowy-user/src/entities/user_update.rs index 708c64375f..6c62037dce 100644 --- a/rust-lib/flowy-user/src/entities/user_update.rs +++ b/rust-lib/flowy-user/src/entities/user_update.rs @@ -72,11 +72,7 @@ impl TryInto for UpdateUserRequest { None => None, Some(name) => Some( UserName::parse(name) - .map_err(|e| { - ErrorBuilder::new(UserErrCode::UserNameInvalid) - .msg(e) - .build() - })? + .map_err(|e| ErrorBuilder::new(e).build())? .0, ), }; @@ -85,7 +81,7 @@ impl TryInto for UpdateUserRequest { None => None, Some(email) => Some( UserEmail::parse(email) - .map_err(|e| ErrorBuilder::new(UserErrCode::EmailInvalid).msg(e).build())? + .map_err(|e| ErrorBuilder::new(e).build())? .0, ), }; @@ -107,11 +103,7 @@ impl TryInto for UpdateUserRequest { None => None, Some(password) => Some( UserPassword::parse(password) - .map_err(|e| { - ErrorBuilder::new(UserErrCode::PasswordInvalid) - .msg(e) - .build() - })? + .map_err(|e| ErrorBuilder::new(e).build())? .0, ), }; diff --git a/rust-lib/flowy-user/src/errors.rs b/rust-lib/flowy-user/src/errors.rs index a5883078e3..a908e6607f 100644 --- a/rust-lib/flowy-user/src/errors.rs +++ b/rust-lib/flowy-user/src/errors.rs @@ -47,21 +47,37 @@ pub enum UserErrCode { #[display(fmt = "Get current id write lock failed")] WriteCurrentIdFailed = 12, - #[display(fmt = "Email format is not correct")] - EmailInvalid = 20, - #[display(fmt = "Password format is not correct")] - PasswordInvalid = 21, - #[display(fmt = "User name is invalid")] - UserNameInvalid = 22, + #[display(fmt = "Email can not be empty or whitespace")] + EmailIsEmpty = 20, + #[display(fmt = "Email format is not valid")] + EmailFormatInvalid = 21, + #[display(fmt = "Email already exists")] + EmailAlreadyExists = 22, + #[display(fmt = "Password can not be empty or whitespace")] + PasswordIsEmpty = 30, + #[display(fmt = "Password format too long")] + PasswordTooLong = 31, + #[display(fmt = "Password contains forbidden characters.")] + PasswordContainsForbidCharacters = 32, + #[display( + fmt = "Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric" + )] + PasswordFormatInvalid = 33, + #[display(fmt = "User name is too long")] + UserNameTooLong = 40, + #[display(fmt = "User name contain forbidden characters")] + UserNameContainsForbiddenCharacters = 41, + #[display(fmt = "User name can not be empty or whitespace")] + UserNameIsEmpty = 42, #[display(fmt = "User workspace is invalid")] - UserWorkspaceInvalid = 23, + UserWorkspaceInvalid = 50, #[display(fmt = "User id is invalid")] - UserIdInvalid = 24, + UserIdInvalid = 51, #[display(fmt = "Create user default workspace failed")] - CreateDefaultWorkspaceFailed = 25, + CreateDefaultWorkspaceFailed = 52, #[display(fmt = "User default workspace already exists")] - DefaultWorkspaceAlreadyExist = 26, + DefaultWorkspaceAlreadyExist = 53, #[display(fmt = "Network error")] NetworkError = 100, @@ -116,8 +132,8 @@ impl std::convert::From for UserError { } } -impl std::convert::From for UserError { - fn from(error: flowy_net::errors::NetworkError) -> Self { +impl std::convert::From for UserError { + fn from(error: flowy_net::response::ServerError) -> Self { ErrorBuilder::new(UserErrCode::NetworkError) .error(error) .build() @@ -134,5 +150,12 @@ impl flowy_dispatch::Error for UserError { pub type ErrorBuilder = flowy_infra::errors::Builder; impl flowy_infra::errors::Build for UserError { - fn build(code: UserErrCode, msg: String) -> Self { UserError::new(code, &msg) } + fn build(code: UserErrCode, msg: String) -> Self { + let msg = if msg.is_empty() { + format!("{}", code) + } else { + msg + }; + UserError::new(code, &msg) + } } diff --git a/rust-lib/flowy-user/src/protobuf/model/errors.rs b/rust-lib/flowy-user/src/protobuf/model/errors.rs index c59e2d831e..c59ed813aa 100644 --- a/rust-lib/flowy-user/src/protobuf/model/errors.rs +++ b/rust-lib/flowy-user/src/protobuf/model/errors.rs @@ -225,13 +225,20 @@ pub enum UserErrCode { UserNotLoginYet = 10, ReadCurrentIdFailed = 11, WriteCurrentIdFailed = 12, - EmailInvalid = 20, - PasswordInvalid = 21, - UserNameInvalid = 22, - UserWorkspaceInvalid = 23, - UserIdInvalid = 24, - CreateDefaultWorkspaceFailed = 25, - DefaultWorkspaceAlreadyExist = 26, + EmailIsEmpty = 20, + EmailFormatInvalid = 21, + EmailAlreadyExists = 22, + PasswordIsEmpty = 30, + PasswordTooLong = 31, + PasswordContainsForbidCharacters = 32, + PasswordFormatInvalid = 33, + UserNameTooLong = 40, + UserNameContainsForbiddenCharacters = 41, + UserNameIsEmpty = 42, + UserWorkspaceInvalid = 50, + UserIdInvalid = 51, + CreateDefaultWorkspaceFailed = 52, + DefaultWorkspaceAlreadyExist = 53, NetworkError = 100, } @@ -252,13 +259,20 @@ impl ::protobuf::ProtobufEnum for UserErrCode { 10 => ::std::option::Option::Some(UserErrCode::UserNotLoginYet), 11 => ::std::option::Option::Some(UserErrCode::ReadCurrentIdFailed), 12 => ::std::option::Option::Some(UserErrCode::WriteCurrentIdFailed), - 20 => ::std::option::Option::Some(UserErrCode::EmailInvalid), - 21 => ::std::option::Option::Some(UserErrCode::PasswordInvalid), - 22 => ::std::option::Option::Some(UserErrCode::UserNameInvalid), - 23 => ::std::option::Option::Some(UserErrCode::UserWorkspaceInvalid), - 24 => ::std::option::Option::Some(UserErrCode::UserIdInvalid), - 25 => ::std::option::Option::Some(UserErrCode::CreateDefaultWorkspaceFailed), - 26 => ::std::option::Option::Some(UserErrCode::DefaultWorkspaceAlreadyExist), + 20 => ::std::option::Option::Some(UserErrCode::EmailIsEmpty), + 21 => ::std::option::Option::Some(UserErrCode::EmailFormatInvalid), + 22 => ::std::option::Option::Some(UserErrCode::EmailAlreadyExists), + 30 => ::std::option::Option::Some(UserErrCode::PasswordIsEmpty), + 31 => ::std::option::Option::Some(UserErrCode::PasswordTooLong), + 32 => ::std::option::Option::Some(UserErrCode::PasswordContainsForbidCharacters), + 33 => ::std::option::Option::Some(UserErrCode::PasswordFormatInvalid), + 40 => ::std::option::Option::Some(UserErrCode::UserNameTooLong), + 41 => ::std::option::Option::Some(UserErrCode::UserNameContainsForbiddenCharacters), + 42 => ::std::option::Option::Some(UserErrCode::UserNameIsEmpty), + 50 => ::std::option::Option::Some(UserErrCode::UserWorkspaceInvalid), + 51 => ::std::option::Option::Some(UserErrCode::UserIdInvalid), + 52 => ::std::option::Option::Some(UserErrCode::CreateDefaultWorkspaceFailed), + 53 => ::std::option::Option::Some(UserErrCode::DefaultWorkspaceAlreadyExist), 100 => ::std::option::Option::Some(UserErrCode::NetworkError), _ => ::std::option::Option::None } @@ -276,9 +290,16 @@ impl ::protobuf::ProtobufEnum for UserErrCode { UserErrCode::UserNotLoginYet, UserErrCode::ReadCurrentIdFailed, UserErrCode::WriteCurrentIdFailed, - UserErrCode::EmailInvalid, - UserErrCode::PasswordInvalid, - UserErrCode::UserNameInvalid, + UserErrCode::EmailIsEmpty, + UserErrCode::EmailFormatInvalid, + UserErrCode::EmailAlreadyExists, + UserErrCode::PasswordIsEmpty, + UserErrCode::PasswordTooLong, + UserErrCode::PasswordContainsForbidCharacters, + UserErrCode::PasswordFormatInvalid, + UserErrCode::UserNameTooLong, + UserErrCode::UserNameContainsForbiddenCharacters, + UserErrCode::UserNameIsEmpty, UserErrCode::UserWorkspaceInvalid, UserErrCode::UserIdInvalid, UserErrCode::CreateDefaultWorkspaceFailed, @@ -314,62 +335,80 @@ impl ::protobuf::reflect::ProtobufValue for UserErrCode { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x0cerrors.proto\"?\n\tUserError\x12\x20\n\x04code\x18\x01\x20\x01(\ \x0e2\x0c.UserErrCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03m\ - sg*\xc8\x03\n\x0bUserErrCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16Use\ + sg*\x8c\x05\n\x0bUserErrCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16Use\ rDatabaseInitFailed\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\x14\ \n\x10SqlInternalError\x10\x06\x12\x13\n\x0fUserNotLoginYet\x10\n\x12\ \x17\n\x13ReadCurrentIdFailed\x10\x0b\x12\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\x14UserWorkspace\ - Invalid\x10\x17\x12\x11\n\rUserIdInvalid\x10\x18\x12\x20\n\x1cCreateDefa\ - ultWorkspaceFailed\x10\x19\x12\x20\n\x1cDefaultWorkspaceAlreadyExist\x10\ - \x1a\x12\x10\n\x0cNetworkError\x10dJ\x92\x07\n\x06\x12\x04\0\0\x19\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\x19\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x03\x04\x0f\n\x0c\n\x05\x04\ - \0\x02\0\x01\x12\x03\x03\x10\x14\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ - \x17\x18\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\x19\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x10\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\x14\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x17\x18\n\x0b\n\ - \x04\x05\0\x02\x07\x12\x03\x0e\x04\x19\n\x0c\n\x05\x05\0\x02\x07\x01\x12\ - \x03\x0e\x04\x13\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x16\x18\n\x0b\ - \n\x04\x05\0\x02\x08\x12\x03\x0f\x04\x1d\n\x0c\n\x05\x05\0\x02\x08\x01\ - \x12\x03\x0f\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x1a\x1c\n\ - \x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04\x1e\n\x0c\n\x05\x05\0\x02\t\x01\ - \x12\x03\x10\x04\x18\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\x1b\x1d\n\ - \x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\x16\n\x0c\n\x05\x05\0\x02\n\x01\ - \x12\x03\x11\x04\x10\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x13\x15\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\x19\n\x0c\n\x05\x05\0\x02\ - \x0c\x01\x12\x03\x13\x04\x13\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\ - \x16\x18\n\x0b\n\x04\x05\0\x02\r\x12\x03\x14\x04\x1e\n\x0c\n\x05\x05\0\ - \x02\r\x01\x12\x03\x14\x04\x18\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\ - \x1b\x1d\n\x0b\n\x04\x05\0\x02\x0e\x12\x03\x15\x04\x17\n\x0c\n\x05\x05\0\ - \x02\x0e\x01\x12\x03\x15\x04\x11\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\ - \x15\x14\x16\n\x0b\n\x04\x05\0\x02\x0f\x12\x03\x16\x04&\n\x0c\n\x05\x05\ - \0\x02\x0f\x01\x12\x03\x16\x04\x20\n\x0c\n\x05\x05\0\x02\x0f\x02\x12\x03\ - \x16#%\n\x0b\n\x04\x05\0\x02\x10\x12\x03\x17\x04&\n\x0c\n\x05\x05\0\x02\ - \x10\x01\x12\x03\x17\x04\x20\n\x0c\n\x05\x05\0\x02\x10\x02\x12\x03\x17#%\ - \n\x0b\n\x04\x05\0\x02\x11\x12\x03\x18\x04\x17\n\x0c\n\x05\x05\0\x02\x11\ - \x01\x12\x03\x18\x04\x10\n\x0c\n\x05\x05\0\x02\x11\x02\x12\x03\x18\x13\ - \x16b\x06proto3\ + \x10\x0c\x12\x10\n\x0cEmailIsEmpty\x10\x14\x12\x16\n\x12EmailFormatInval\ + id\x10\x15\x12\x16\n\x12EmailAlreadyExists\x10\x16\x12\x13\n\x0fPassword\ + IsEmpty\x10\x1e\x12\x13\n\x0fPasswordTooLong\x10\x1f\x12$\n\x20PasswordC\ + ontainsForbidCharacters\x10\x20\x12\x19\n\x15PasswordFormatInvalid\x10!\ + \x12\x13\n\x0fUserNameTooLong\x10(\x12'\n#UserNameContainsForbiddenChara\ + cters\x10)\x12\x13\n\x0fUserNameIsEmpty\x10*\x12\x18\n\x14UserWorkspaceI\ + nvalid\x102\x12\x11\n\rUserIdInvalid\x103\x12\x20\n\x1cCreateDefaultWork\ + spaceFailed\x104\x12\x20\n\x1cDefaultWorkspaceAlreadyExist\x105\x12\x10\ + \n\x0cNetworkError\x10dJ\xb1\t\n\x06\x12\x04\0\0\x20\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\x19\n\ + \x0c\n\x05\x04\0\x02\0\x06\x12\x03\x03\x04\x0f\n\x0c\n\x05\x04\0\x02\0\ + \x01\x12\x03\x03\x10\x14\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x17\x18\ + \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\x20\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x10\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\x14\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x17\x18\n\x0b\n\x04\x05\ + \0\x02\x07\x12\x03\x0e\x04\x19\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\ + \x04\x13\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x16\x18\n\x0b\n\x04\ + \x05\0\x02\x08\x12\x03\x0f\x04\x1d\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\ + \x0f\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x1a\x1c\n\x0b\n\ + \x04\x05\0\x02\t\x12\x03\x10\x04\x1e\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\ + \x10\x04\x18\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\x1b\x1d\n\x0b\n\x04\ + \x05\0\x02\n\x12\x03\x11\x04\x16\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\ + \x04\x10\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x13\x15\n\x0b\n\x04\x05\ + \0\x02\x0b\x12\x03\x12\x04\x1c\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\ + \x04\x16\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x19\x1b\n\x0b\n\x04\ + \x05\0\x02\x0c\x12\x03\x13\x04\x1c\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\ + \x13\x04\x16\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x19\x1b\n\x0b\n\ + \x04\x05\0\x02\r\x12\x03\x14\x04\x19\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\ + \x14\x04\x13\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x16\x18\n\x0b\n\x04\ + \x05\0\x02\x0e\x12\x03\x15\x04\x19\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\ + \x15\x04\x13\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\x15\x16\x18\n\x0b\n\ + \x04\x05\0\x02\x0f\x12\x03\x16\x04*\n\x0c\n\x05\x05\0\x02\x0f\x01\x12\ + \x03\x16\x04$\n\x0c\n\x05\x05\0\x02\x0f\x02\x12\x03\x16')\n\x0b\n\x04\ + \x05\0\x02\x10\x12\x03\x17\x04\x1f\n\x0c\n\x05\x05\0\x02\x10\x01\x12\x03\ + \x17\x04\x19\n\x0c\n\x05\x05\0\x02\x10\x02\x12\x03\x17\x1c\x1e\n\x0b\n\ + \x04\x05\0\x02\x11\x12\x03\x18\x04\x19\n\x0c\n\x05\x05\0\x02\x11\x01\x12\ + \x03\x18\x04\x13\n\x0c\n\x05\x05\0\x02\x11\x02\x12\x03\x18\x16\x18\n\x0b\ + \n\x04\x05\0\x02\x12\x12\x03\x19\x04-\n\x0c\n\x05\x05\0\x02\x12\x01\x12\ + \x03\x19\x04'\n\x0c\n\x05\x05\0\x02\x12\x02\x12\x03\x19*,\n\x0b\n\x04\ + \x05\0\x02\x13\x12\x03\x1a\x04\x19\n\x0c\n\x05\x05\0\x02\x13\x01\x12\x03\ + \x1a\x04\x13\n\x0c\n\x05\x05\0\x02\x13\x02\x12\x03\x1a\x16\x18\n\x0b\n\ + \x04\x05\0\x02\x14\x12\x03\x1b\x04\x1e\n\x0c\n\x05\x05\0\x02\x14\x01\x12\ + \x03\x1b\x04\x18\n\x0c\n\x05\x05\0\x02\x14\x02\x12\x03\x1b\x1b\x1d\n\x0b\ + \n\x04\x05\0\x02\x15\x12\x03\x1c\x04\x17\n\x0c\n\x05\x05\0\x02\x15\x01\ + \x12\x03\x1c\x04\x11\n\x0c\n\x05\x05\0\x02\x15\x02\x12\x03\x1c\x14\x16\n\ + \x0b\n\x04\x05\0\x02\x16\x12\x03\x1d\x04&\n\x0c\n\x05\x05\0\x02\x16\x01\ + \x12\x03\x1d\x04\x20\n\x0c\n\x05\x05\0\x02\x16\x02\x12\x03\x1d#%\n\x0b\n\ + \x04\x05\0\x02\x17\x12\x03\x1e\x04&\n\x0c\n\x05\x05\0\x02\x17\x01\x12\ + \x03\x1e\x04\x20\n\x0c\n\x05\x05\0\x02\x17\x02\x12\x03\x1e#%\n\x0b\n\x04\ + \x05\0\x02\x18\x12\x03\x1f\x04\x17\n\x0c\n\x05\x05\0\x02\x18\x01\x12\x03\ + \x1f\x04\x10\n\x0c\n\x05\x05\0\x02\x18\x02\x12\x03\x1f\x13\x16b\x06proto\ + 3\ "; 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/errors.proto b/rust-lib/flowy-user/src/protobuf/proto/errors.proto index 2b2cc7b4b9..85461a5afc 100644 --- a/rust-lib/flowy-user/src/protobuf/proto/errors.proto +++ b/rust-lib/flowy-user/src/protobuf/proto/errors.proto @@ -15,12 +15,19 @@ enum UserErrCode { UserNotLoginYet = 10; ReadCurrentIdFailed = 11; WriteCurrentIdFailed = 12; - EmailInvalid = 20; - PasswordInvalid = 21; - UserNameInvalid = 22; - UserWorkspaceInvalid = 23; - UserIdInvalid = 24; - CreateDefaultWorkspaceFailed = 25; - DefaultWorkspaceAlreadyExist = 26; + EmailIsEmpty = 20; + EmailFormatInvalid = 21; + EmailAlreadyExists = 22; + PasswordIsEmpty = 30; + PasswordTooLong = 31; + PasswordContainsForbidCharacters = 32; + PasswordFormatInvalid = 33; + UserNameTooLong = 40; + UserNameContainsForbiddenCharacters = 41; + UserNameIsEmpty = 42; + UserWorkspaceInvalid = 50; + UserIdInvalid = 51; + CreateDefaultWorkspaceFailed = 52; + DefaultWorkspaceAlreadyExist = 53; NetworkError = 100; } diff --git a/rust-lib/flowy-user/tests/server/main.rs b/rust-lib/flowy-user/tests/server/main.rs new file mode 100644 index 0000000000..3e9a615104 --- /dev/null +++ b/rust-lib/flowy-user/tests/server/main.rs @@ -0,0 +1 @@ +mod user_test; diff --git a/rust-lib/flowy-user/tests/server/user_test.rs b/rust-lib/flowy-user/tests/server/user_test.rs new file mode 100644 index 0000000000..9f34ecba5e --- /dev/null +++ b/rust-lib/flowy-user/tests/server/user_test.rs @@ -0,0 +1,13 @@ +use flowy_user::prelude::*; + +#[tokio::test] +async fn user_register_test() { + let server = UserServerImpl {}; + + let params = SignUpParams { + email: "annie@appflowy.io".to_string(), + name: "annie".to_string(), + password: "123".to_string(), + }; + let result = server.sign_up(params).await.unwrap(); +}