diff --git a/.run/ProtoBuf_Gen.run.xml b/.run/ProtoBuf_Gen.run.xml
new file mode 100644
index 0000000000..2fdf466875
--- /dev/null
+++ b/.run/ProtoBuf_Gen.run.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Run backend.run.xml b/.run/Run backend.run.xml
new file mode 100644
index 0000000000..840a367809
--- /dev/null
+++ b/.run/Run backend.run.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/dart-event.run.xml b/.run/dart-event.run.xml
new file mode 100644
index 0000000000..71ac27e8e7
--- /dev/null
+++ b/.run/dart-event.run.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/backend/.dockerignore b/backend/.dockerignore
index 1719710ae1..5ebf0cb3f8 100644
--- a/backend/.dockerignore
+++ b/backend/.dockerignore
@@ -7,4 +7,5 @@ tests/
Dockerfile
scripts/
migrations/
-app_flowy/
\ No newline at end of file
+app_flowy/
+rust-lib/target/
\ No newline at end of file
diff --git a/backend/Dockerfile b/backend/Dockerfile
index b642fe993f..dc50419889 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,15 +1,58 @@
-# We use the latest Rust stable release as base image
+
FROM rust:1.53.0
# Let's switch our working directory to `app` (equivalent to `cd app`)
# The `app` folder will be created for us by Docker in case it does not
# exist already.
WORKDIR /app
-# Copy all files from our working environment to our Docker image
COPY . .
-# Let's build our binary!
-# We'll use the release profile to make it fast
+
WORKDIR /app/backend
+ENV SQLX_OFFLINE true
+ENV APP_ENVIRONMENT production
RUN cargo build --release
+
# When `docker run` is executed, launch the binary!
ENTRYPOINT ["./target/release/backend"]
+
+#
+
+
+
+## We use the latest Rust stable release as base image
+#FROM lukemathwalker/cargo-chef:latest-rust-1.53.0 as planner
+#WORKDIR /app
+#COPY . .
+#
+#WORKDIR /app/backend
+#RUN cargo chef prepare --recipe-path recipe.json
+#
+#FROM lukemathwalker/cargo-chef:latest-rust-1.53.0 as cacher
+#WORKDIR /app/backend
+#COPY --from=planner /app/backend/recipe.json recipe.json
+## Build our project dependencies, not our application!
+#RUN cargo chef cook --release --recipe-path recipe.json
+#
+#FROM rust:1.53.0 AS builder
+#WORKDIR /app/backend
+## Copy over the cached dependencies
+#COPY --from=cacher /app/backend/target target
+#COPY --from=cacher /usr/local/cargo /usr/local/cargo
+#COPY . .
+#
+#ENV SQLX_OFFLINE true
+#RUN cargo build --release --bin backend
+#
+#
+#FROM debian:buster-slim AS runtime
+#WORKDIR /app/backend
+#RUN apt-get update -y \
+# && apt-get install -y --no-install-recommends openssl \
+# # Clean up
+# && apt-get autoremove -y \
+# && apt-get clean -y \
+# && rm -rf /var/lib/apt/lists/*
+#COPY --from=builder /app/backend/target/release/backend backend
+##COPY configuration configuration
+#ENV APP_ENVIRONMENT production
+#ENTRYPOINT ["./backend"]
diff --git a/backend/configuration/production.yaml b/backend/configuration/production.yaml
index cd4608ab4f..1de1c6bb54 100644
--- a/backend/configuration/production.yaml
+++ b/backend/configuration/production.yaml
@@ -1,4 +1,4 @@
application:
host: 0.0.0.0
database:
- require_ssl: true
+ require_ssl: false
diff --git a/backend/doc/database_setup.md b/backend/doc/database_setup.md
index 83c82cbde0..01a701c604 100644
--- a/backend/doc/database_setup.md
+++ b/backend/doc/database_setup.md
@@ -27,4 +27,8 @@ export DB_PORT=5433
![img_1.png](img_1.png)
-[Docker command](https://docs.docker.com/engine/reference/commandline/builder_prune/)
\ No newline at end of file
+[Docker command](https://docs.docker.com/engine/reference/commandline/builder_prune/)
+
+### Run
+By default, Docker images do not expose their ports to the underlying host machine. We need to do it explicitly using the -p flag.
+`docker run -p 8000:8000 backend`
\ No newline at end of file
diff --git a/backend/src/application.rs b/backend/src/application.rs
index ec617cd2fd..0f8a895e93 100644
--- a/backend/src/application.rs
+++ b/backend/src/application.rs
@@ -63,7 +63,10 @@ async fn init_app_context(configuration: &Settings) -> Arc {
let pg_pool = Arc::new(
get_connection_pool(&configuration.database)
.await
- .expect("Failed to connect to Postgres."),
+ .expect(&format!(
+ "Failed to connect to Postgres {:?}.",
+ configuration.database
+ )),
);
let ws_server = WSServer::new().start();
@@ -77,7 +80,7 @@ async fn init_app_context(configuration: &Settings) -> Arc {
pub async fn get_connection_pool(configuration: &DatabaseSettings) -> Result {
PgPoolOptions::new()
- .connect_timeout(std::time::Duration::from_secs(2))
+ .connect_timeout(std::time::Duration::from_secs(5))
.connect_with(configuration.with_db())
.await
}
diff --git a/backend/src/config/configuration.rs b/backend/src/config/configuration.rs
index d76de5463f..48f26eb0f1 100644
--- a/backend/src/config/configuration.rs
+++ b/backend/src/config/configuration.rs
@@ -8,15 +8,22 @@ pub struct Settings {
pub application: ApplicationSettings,
}
+// We are using 127.0.0.1 as our host in address, we are instructing our
+// application to only accept connections coming from the same machine. However,
+// request from the hose machine which is not seen as local by our Docker image.
+//
+// Using 0.0.0.0 as host to instruct our application to accept connections from
+// any network interface. So using 127.0.0.1 for our local development and set
+// it to 0.0.0.0 in our Docker images.
+//
#[derive(serde::Deserialize, Clone)]
pub struct ApplicationSettings {
#[serde(deserialize_with = "deserialize_number_from_string")]
pub port: u16,
pub host: String,
- pub base_url: String,
}
-#[derive(serde::Deserialize, Clone)]
+#[derive(serde::Deserialize, Clone, Debug)]
pub struct DatabaseSettings {
pub username: String,
pub password: String,
diff --git a/backend/src/routers/user.rs b/backend/src/routers/user.rs
index f9b90a8710..fb33abf10b 100644
--- a/backend/src/routers/user.rs
+++ b/backend/src/routers/user.rs
@@ -14,11 +14,9 @@ pub async fn register(
_request: HttpRequest,
payload: Payload,
auth: Data>,
-) -> Result {
+) -> Result {
let params: SignUpParams = parse_from_payload(payload).await?;
- let _ = auth.sign_up(params).await?;
-
- let resp = FlowyResponse::success();
+ let resp = auth.sign_up(params).await?;
Ok(resp.into())
}
diff --git a/backend/src/user_service/auth.rs b/backend/src/user_service/auth.rs
index 3e590cfc00..dd8cbe76e9 100644
--- a/backend/src/user_service/auth.rs
+++ b/backend/src/user_service/auth.rs
@@ -1,5 +1,5 @@
use chrono::Utc;
-use flowy_net::response::{ServerCode, ServerError};
+use flowy_net::response::{FlowyResponse, ServerCode, ServerError};
use flowy_user::{entities::SignUpResponse, protobuf::SignUpParams};
use sqlx::PgPool;
use std::sync::Arc;
@@ -11,15 +11,16 @@ pub struct Auth {
impl Auth {
pub fn new(db_pool: Arc) -> Self { Self { db_pool } }
- pub async fn sign_up(&self, params: SignUpParams) -> Result {
+ pub async fn sign_up(&self, params: SignUpParams) -> Result {
// email exist?
// generate user id
+ let uuid = uuid::Uuid::new_v4();
let result = sqlx::query!(
r#"
INSERT INTO user_table (id, email, name, create_time, password)
VALUES ($1, $2, $3, $4, $5)
"#,
- uuid::Uuid::new_v4(),
+ uuid,
params.email,
params.name,
Utc::now(),
@@ -28,11 +29,14 @@ impl Auth {
.execute(self.db_pool.as_ref())
.await;
- let response = SignUpResponse {
- uid: "".to_string(),
- name: "".to_string(),
- email: "".to_string(),
+ let data = SignUpResponse {
+ uid: uuid.to_string(),
+ name: params.name,
+ email: params.email,
};
+
+ let response = FlowyResponse::from(data, "", ServerCode::Success)?;
+
Ok(response)
}
diff --git a/rust-lib/Cargo.toml b/rust-lib/Cargo.toml
index 5815cabc35..75b7f6b5f1 100644
--- a/rust-lib/Cargo.toml
+++ b/rust-lib/Cargo.toml
@@ -19,5 +19,7 @@ members = [
"flowy-net",
]
+exclude = ["../backend"]
+
[profile.dev]
split-debuginfo = "unpacked"
diff --git a/rust-lib/flowy-dispatch/src/byte_trait.rs b/rust-lib/flowy-dispatch/src/byte_trait.rs
index 531d4aab7a..beb6e4a614 100644
--- a/rust-lib/flowy-dispatch/src/byte_trait.rs
+++ b/rust-lib/flowy-dispatch/src/byte_trait.rs
@@ -1,6 +1,6 @@
use crate::errors::{DispatchError, InternalError};
use bytes::Bytes;
-use protobuf::ProtobufError;
+
use std::convert::TryFrom;
// To bytes
diff --git a/rust-lib/flowy-dispatch/src/errors/errors.rs b/rust-lib/flowy-dispatch/src/errors/errors.rs
index 051d5bfd26..4ca65400af 100644
--- a/rust-lib/flowy-dispatch/src/errors/errors.rs
+++ b/rust-lib/flowy-dispatch/src/errors/errors.rs
@@ -5,7 +5,7 @@ use crate::{
};
use bytes::Bytes;
use dyn_clone::DynClone;
-use protobuf::ProtobufError;
+
use serde::{Serialize, Serializer};
use std::fmt;
use tokio::{sync::mpsc::error::SendError, task::JoinError};
diff --git a/rust-lib/flowy-dispatch/src/response/response.rs b/rust-lib/flowy-dispatch/src/response/response.rs
index 95f26c047c..8208589242 100644
--- a/rust-lib/flowy-dispatch/src/response/response.rs
+++ b/rust-lib/flowy-dispatch/src/response/response.rs
@@ -1,7 +1,7 @@
use crate::{
byte_trait::FromBytes,
data::Data,
- errors::{DispatchError, InternalError},
+ errors::DispatchError,
request::{EventRequest, Payload},
response::Responder,
};
diff --git a/rust-lib/flowy-net/src/config.rs b/rust-lib/flowy-net/src/config.rs
index 8440c3996b..51aef47acc 100644
--- a/rust-lib/flowy-net/src/config.rs
+++ b/rust-lib/flowy-net/src/config.rs
@@ -1,6 +1,6 @@
use lazy_static::lazy_static;
-pub const HOST: &'static str = "http://0.0.0.0:3030";
+pub const HOST: &'static str = "http://localhost:8000";
lazy_static! {
pub static ref SIGN_UP_URL: String = format!("{}/user/register", HOST);
diff --git a/rust-lib/flowy-net/src/errors/errors.rs b/rust-lib/flowy-net/src/errors/errors.rs
deleted file mode 100644
index 6a7b431a7f..0000000000
--- a/rust-lib/flowy-net/src/errors/errors.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-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
deleted file mode 100644
index 852f5c0f5e..0000000000
--- a/rust-lib/flowy-net/src/errors/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-mod errors;
-
-pub use errors::*;
diff --git a/rust-lib/flowy-net/src/lib.rs b/rust-lib/flowy-net/src/lib.rs
index a0b6d841ce..2426021c58 100644
--- a/rust-lib/flowy-net/src/lib.rs
+++ b/rust-lib/flowy-net/src/lib.rs
@@ -1,6 +1,4 @@
-pub mod errors;
-pub mod future;
-
pub mod config;
+pub mod future;
pub mod request;
pub mod response;
diff --git a/rust-lib/flowy-net/src/request/request.rs b/rust-lib/flowy-net/src/request/request.rs
index 5c3532f5e4..1617063649 100644
--- a/rust-lib/flowy-net/src/request/request.rs
+++ b/rust-lib/flowy-net/src/request/request.rs
@@ -1,23 +1,13 @@
-use crate::{future::ResultFuture, response::ServerError};
+use crate::response::{FlowyResponse, ServerCode, ServerError};
use bytes::Bytes;
+use hyper::http;
use protobuf::{Message, ProtobufError};
-use reqwest::{Client, Error, Response};
+use reqwest::{Client, Response};
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
-// T1: TryInto + Send + Sync + 'static,
-// T2: TryFrom + Send + Sync + 'static,
-// {
-// let url = url.to_owned();
-// ResultFuture::new(async move { post(url, data).await })
-// }
+use tokio::sync::oneshot;
pub async fn http_post(url: &str, data: T1) -> Result
where
@@ -37,9 +27,9 @@ where
let response = rx.await??;
if response.status() == http::StatusCode::OK {
let response_bytes = response.bytes().await?;
- let data = T2::try_from(response_bytes)?;
+ let flowy_resp: FlowyResponse = serde_json::from_slice(&response_bytes).unwrap();
+ let data = T2::try_from(flowy_resp.data)?;
Ok(data)
-
} else {
Err(ServerError {
code: ServerCode::InternalError,
diff --git a/rust-lib/flowy-net/src/response/response.rs b/rust-lib/flowy-net/src/response/response.rs
index 7b2b7108ab..ef5603978a 100644
--- a/rust-lib/flowy-net/src/response/response.rs
+++ b/rust-lib/flowy-net/src/response/response.rs
@@ -1,6 +1,7 @@
-use serde::{Serialize, __private::Formatter};
+use bytes::Bytes;
+use serde::{Deserialize, Serialize, __private::Formatter};
use serde_repr::*;
-use std::{error::Error, fmt};
+use std::{convert::TryInto, error::Error, fmt};
use tokio::sync::oneshot::error::RecvError;
#[derive(Debug)]
@@ -16,11 +17,11 @@ impl std::fmt::Display for ServerError {
}
}
-impl std::convert::From<&ServerError> for FlowyResponse {
+impl std::convert::From<&ServerError> for FlowyResponse {
fn from(error: &ServerError) -> Self {
FlowyResponse {
msg: error.msg.clone(),
- data: None,
+ data: Bytes::from(vec![]),
code: error.code.clone(),
}
}
@@ -43,15 +44,15 @@ pub enum ServerCode {
ConnectCancel = 11,
}
-#[derive(Debug, Serialize)]
-pub struct FlowyResponse {
+#[derive(Debug, Serialize, Deserialize)]
+pub struct FlowyResponse {
pub msg: String,
- pub data: Option,
+ pub data: Bytes,
pub code: ServerCode,
}
-impl FlowyResponse {
- pub fn new(data: Option, msg: &str, code: ServerCode) -> Self {
+impl FlowyResponse {
+ pub fn new(data: Bytes, msg: &str, code: ServerCode) -> Self {
FlowyResponse {
msg: msg.to_owned(),
data,
@@ -59,16 +60,13 @@ impl FlowyResponse {
}
}
- pub fn from_data(data: T, msg: &str, code: ServerCode) -> Self {
- Self::new(Some(data), msg, code)
- }
-}
-
-impl FlowyResponse {
- pub fn success() -> Self { Self::from_msg("", ServerCode::Success) }
-
- pub fn from_msg(msg: &str, code: ServerCode) -> Self {
- Self::new(Some("".to_owned()), msg, code)
+ pub fn from>(
+ data: T,
+ msg: &str,
+ code: ServerCode,
+ ) -> Result {
+ let bytes: Bytes = data.try_into()?;
+ Ok(Self::new(bytes, msg, code))
}
}
@@ -90,6 +88,16 @@ impl std::convert::From for ServerError {
}
}
+impl std::convert::From for ServerError {
+ fn from(e: serde_json::Error) -> Self {
+ let msg = format!("Serial error: {:?}", e);
+ ServerError {
+ code: ServerCode::SerdeError,
+ msg,
+ }
+ }
+}
+
impl std::convert::From for ServerError {
fn from(error: reqwest::Error) -> Self {
if error.is_timeout() {
@@ -121,9 +129,7 @@ impl std::convert::From for ServerError {
code = ServerCode::ConnectCancel;
}
- if hyper_error.is_timeout() {
-
- }
+ if hyper_error.is_timeout() {}
ServerError { code, msg }
},
diff --git a/rust-lib/flowy-net/src/response/response_http.rs b/rust-lib/flowy-net/src/response/response_http.rs
index 8c33bd6e11..689823bf2b 100644
--- a/rust-lib/flowy-net/src/response/response_http.rs
+++ b/rust-lib/flowy-net/src/response/response_http.rs
@@ -1,30 +1,14 @@
use crate::response::*;
use actix_web::{body::Body, error::ResponseError, BaseHttpResponse, HttpResponse};
+use reqwest::StatusCode;
use serde::Serialize;
-impl ServerError {
- fn http_response(&self) -> HttpResponse {
- let resp: FlowyResponse = self.into();
- HttpResponse::Ok().json(resp)
- }
-}
-
impl ResponseError for ServerError {
- fn error_response(&self) -> HttpResponse { self.http_response().into() }
-}
-
-impl std::convert::Into for FlowyResponse {
- 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 {
- code: ServerCode::SerdeError,
- msg,
- }
- .error_response()
- },
- }
+ fn error_response(&self) -> HttpResponse {
+ let response: FlowyResponse = self.into();
+ response.into()
}
}
+impl std::convert::Into for FlowyResponse {
+ fn into(self) -> HttpResponse { HttpResponse::Ok().json(self) }
+}
diff --git a/rust-lib/flowy-net/src/response/response_serde.rs b/rust-lib/flowy-net/src/response/response_serde.rs
index b81b61a0cd..f8a7962e8b 100644
--- a/rust-lib/flowy-net/src/response/response_serde.rs
+++ b/rust-lib/flowy-net/src/response/response_serde.rs
@@ -1,128 +1,129 @@
-use crate::response::{FlowyResponse, ServerCode};
-use serde::{
- de::{self, MapAccess, Visitor},
- Deserialize,
- Deserializer,
- Serialize,
-};
-use std::{fmt, marker::PhantomData, str::FromStr};
-
-pub trait ServerData<'a>: Serialize + Deserialize<'a> + FromStr {}
-impl<'de, T: ServerData<'de>> Deserialize<'de> for FlowyResponse {
- fn deserialize(deserializer: D) -> Result
- where
- D: Deserializer<'de>,
- {
- struct ServerResponseVisitor(PhantomData T>);
- impl<'de, T> Visitor<'de> for ServerResponseVisitor
- where
- T: ServerData<'de>,
- {
- type Value = FlowyResponse;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("struct Duration")
- }
-
- fn visit_map(self, mut map: V) -> Result
- where
- V: MapAccess<'de>,
- {
- let mut msg = None;
- let mut data: Option = None;
- let mut code: Option = None;
- while let Some(key) = map.next_key()? {
- match key {
- "msg" => {
- if msg.is_some() {
- return Err(de::Error::duplicate_field("msg"));
- }
- msg = Some(map.next_value()?);
- },
- "code" => {
- if code.is_some() {
- return Err(de::Error::duplicate_field("code"));
- }
- code = Some(map.next_value()?);
- },
- "data" => {
- if data.is_some() {
- return Err(de::Error::duplicate_field("data"));
- }
- data = match MapAccess::next_value::>(&mut map) {
- Ok(wrapper) => wrapper.value,
- Err(err) => return Err(err),
- };
- },
- _ => panic!(),
- }
- }
- let msg = msg.ok_or_else(|| de::Error::missing_field("msg"))?;
- let code = code.ok_or_else(|| de::Error::missing_field("code"))?;
- Ok(Self::Value::new(data, msg, code))
- }
- }
- const FIELDS: &'static [&'static str] = &["msg", "code", "data"];
- deserializer.deserialize_struct(
- "ServerResponse",
- FIELDS,
- ServerResponseVisitor(PhantomData),
- )
- }
-}
-
-struct DeserializeWith<'de, T: ServerData<'de>> {
- value: Option,
- phantom: PhantomData<&'de ()>,
-}
-
-impl<'de, T: ServerData<'de>> Deserialize<'de> for DeserializeWith<'de, T> {
- fn deserialize(deserializer: D) -> Result
- where
- D: Deserializer<'de>,
- {
- Ok(DeserializeWith {
- value: match string_or_data(deserializer) {
- Ok(val) => val,
- Err(e) => return Err(e),
- },
- phantom: PhantomData,
- })
- }
-}
-
-fn string_or_data<'de, D, T>(deserializer: D) -> Result