mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add user sign up handler
This commit is contained in:
parent
3ae2295193
commit
89c5d5468e
@ -12,7 +12,6 @@ actix-http = "2.2.1"
|
|||||||
actix-web-actors = "3"
|
actix-web-actors = "3"
|
||||||
actix-codec = "0.3"
|
actix-codec = "0.3"
|
||||||
|
|
||||||
|
|
||||||
futures = "0.3.15"
|
futures = "0.3.15"
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
toml = "0.5.8"
|
toml = "0.5.8"
|
||||||
@ -21,7 +20,10 @@ log = "0.4.14"
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
|
derive_more = {version = "0.99", features = ["display"]}
|
||||||
|
protobuf = {version = "2.20.0"}
|
||||||
flowy-log = { path = "../rust-lib/flowy-log" }
|
flowy-log = { path = "../rust-lib/flowy-log" }
|
||||||
|
flowy-user = { path = "../rust-lib/flowy-user" }
|
||||||
|
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
use std::convert::TryFrom;
|
use crate::config::DatabaseConfig;
|
||||||
|
use std::{convert::TryFrom, sync::Arc};
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub http_port: u16,
|
pub http_port: u16,
|
||||||
|
pub database: Arc<DatabaseConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Self { Config { http_port: 3030 } }
|
pub fn new() -> Self {
|
||||||
|
Config {
|
||||||
|
http_port: 3030,
|
||||||
|
database: Arc::new(DatabaseConfig::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn server_addr(&self) -> String { format!("0.0.0.0:{}", self.http_port) }
|
pub fn server_addr(&self) -> String { format!("0.0.0.0:{}", self.http_port) }
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,4 @@ use std::time::Duration;
|
|||||||
|
|
||||||
pub const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(8);
|
pub const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(8);
|
||||||
pub const PING_TIMEOUT: Duration = Duration::from_secs(60);
|
pub const PING_TIMEOUT: Duration = Duration::from_secs(60);
|
||||||
|
pub const MAX_PAYLOAD_SIZE: usize = 262_144; // max payload size is 256k
|
||||||
|
5
backend/src/config/database/config.toml
Normal file
5
backend/src/config/database/config.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
host = "localhost"
|
||||||
|
port = 5433
|
||||||
|
username = "postgres"
|
||||||
|
password = "password"
|
||||||
|
database_name = "flowy"
|
33
backend/src/config/database/database.rs
Normal file
33
backend/src/config/database/database.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct DatabaseConfig {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
port: u16,
|
||||||
|
host: String,
|
||||||
|
database_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DatabaseConfig {
|
||||||
|
pub fn connect_url(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"postgres://{}:{}@{}:{}/{}",
|
||||||
|
self.username, self.password, self.host, self.port, self.database_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_env_db_url(&self) {
|
||||||
|
let url = self.connect_url();
|
||||||
|
std::env::set_var("DATABASE_URL", url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for DatabaseConfig {
|
||||||
|
fn default() -> DatabaseConfig {
|
||||||
|
let toml_str: &str = include_str!("config.toml");
|
||||||
|
let config: DatabaseConfig = toml::from_str(toml_str).unwrap();
|
||||||
|
config.set_env_db_url();
|
||||||
|
config
|
||||||
|
}
|
||||||
|
}
|
3
backend/src/config/database/mod.rs
Normal file
3
backend/src/config/database/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod database;
|
||||||
|
|
||||||
|
pub use database::*;
|
@ -1,5 +1,7 @@
|
|||||||
mod config;
|
mod config;
|
||||||
mod const_define;
|
mod const_define;
|
||||||
|
mod database;
|
||||||
|
|
||||||
pub use config::*;
|
pub use config::*;
|
||||||
pub use const_define::*;
|
pub use const_define::*;
|
||||||
|
pub use database::*;
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
use crate::{config::Config, ws_service::WSServer};
|
use crate::{config::Config, user_service::Auth, ws_service::WSServer};
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
|
|
||||||
|
use sqlx::PgPool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct AppContext {
|
pub struct AppContext {
|
||||||
pub config: Arc<Config>,
|
pub config: Arc<Config>,
|
||||||
pub server: Addr<WSServer>,
|
pub ws_server: Addr<WSServer>,
|
||||||
|
pub db_pool: Arc<PgPool>,
|
||||||
|
pub auth: Arc<Auth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppContext {
|
impl AppContext {
|
||||||
pub fn new(server: Addr<WSServer>) -> Self {
|
pub fn new(
|
||||||
|
config: Arc<Config>,
|
||||||
|
ws_server: Addr<WSServer>,
|
||||||
|
db_pool: Arc<PgPool>,
|
||||||
|
auth: Arc<Auth>,
|
||||||
|
) -> Self {
|
||||||
AppContext {
|
AppContext {
|
||||||
config: Arc::new(Config::new()),
|
config,
|
||||||
server,
|
ws_server,
|
||||||
|
db_pool,
|
||||||
|
auth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ws_server(&self) -> Addr<WSServer> { self.server.clone() }
|
|
||||||
}
|
}
|
||||||
|
7
backend/src/entities/mod.rs
Normal file
7
backend/src/entities/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
mod response;
|
||||||
|
mod response_serde;
|
||||||
|
mod server_code;
|
||||||
|
|
||||||
|
pub use response::*;
|
||||||
|
pub use response_serde::*;
|
||||||
|
pub use server_code::*;
|
45
backend/src/entities/response.rs
Normal file
45
backend/src/entities/response.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::{entities::ServerCode, errors::ServerError};
|
||||||
|
use actix_web::{body::Body, HttpResponse, ResponseError};
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct ServerResponse<T> {
|
||||||
|
pub msg: String,
|
||||||
|
pub data: Option<T>,
|
||||||
|
pub code: ServerCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Serialize> ServerResponse<T> {
|
||||||
|
pub fn new(data: Option<T>, msg: &str, code: ServerCode) -> Self {
|
||||||
|
ServerResponse {
|
||||||
|
msg: msg.to_owned(),
|
||||||
|
data,
|
||||||
|
code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_data(data: T, msg: &str, code: ServerCode) -> Self {
|
||||||
|
Self::new(Some(data), msg, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerResponse<String> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
128
backend/src/entities/response_serde.rs
Normal file
128
backend/src/entities/response_serde.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
use crate::entities::{ServerCode, ServerResponse};
|
||||||
|
use serde::{
|
||||||
|
de::{self, MapAccess, Visitor},
|
||||||
|
Deserialize,
|
||||||
|
Deserializer,
|
||||||
|
Serialize,
|
||||||
|
};
|
||||||
|
use std::{fmt, marker::PhantomData, str::FromStr};
|
||||||
|
|
||||||
|
pub trait ServerData<'a>: Serialize + Deserialize<'a> + FromStr<Err = ()> {}
|
||||||
|
impl<'de, T: ServerData<'de>> Deserialize<'de> for ServerResponse<T> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct ServerResponseVisitor<T>(PhantomData<fn() -> T>);
|
||||||
|
impl<'de, T> Visitor<'de> for ServerResponseVisitor<T>
|
||||||
|
where
|
||||||
|
T: ServerData<'de>,
|
||||||
|
{
|
||||||
|
type Value = ServerResponse<T>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("struct Duration")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
|
||||||
|
where
|
||||||
|
V: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut msg = None;
|
||||||
|
let mut data: Option<T> = None;
|
||||||
|
let mut code: Option<ServerCode> = 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::<DeserializeWith<T>>(&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<T>,
|
||||||
|
phantom: PhantomData<&'de ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, T: ServerData<'de>> Deserialize<'de> for DeserializeWith<'de, T> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
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<Option<T>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
T: ServerData<'de>,
|
||||||
|
{
|
||||||
|
struct StringOrData<T>(PhantomData<fn() -> T>);
|
||||||
|
impl<'de, T: ServerData<'de>> Visitor<'de> for StringOrData<T> {
|
||||||
|
type Value = Option<T>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("string or struct impl deserialize")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
match FromStr::from_str(value) {
|
||||||
|
Ok(val) => Ok(Some(val)),
|
||||||
|
Err(_e) => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
|
||||||
|
where
|
||||||
|
M: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
match Deserialize::deserialize(de::value::MapAccessDeserializer::new(map)) {
|
||||||
|
Ok(val) => Ok(Some(val)),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deserializer.deserialize_any(StringOrData(PhantomData))
|
||||||
|
}
|
12
backend/src/entities/server_code.rs
Normal file
12
backend/src/entities/server_code.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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,
|
||||||
|
}
|
@ -1,3 +1,48 @@
|
|||||||
pub struct ServerError {}
|
use crate::entities::{ServerCode, ServerResponse};
|
||||||
|
use actix_web::{error::ResponseError, HttpResponse};
|
||||||
|
use protobuf::ProtobufError;
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
// pub enum ErrorCode {}
|
#[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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
mod config;
|
mod config;
|
||||||
mod context;
|
mod context;
|
||||||
|
mod entities;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod routers;
|
mod routers;
|
||||||
pub mod startup;
|
pub mod startup;
|
||||||
|
pub mod user_service;
|
||||||
pub mod ws_service;
|
pub mod ws_service;
|
||||||
|
34
backend/src/routers/helper.rs
Normal file
34
backend/src/routers/helper.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
config::MAX_PAYLOAD_SIZE,
|
||||||
|
entities::{ServerCode, ServerResponse},
|
||||||
|
errors::ServerError,
|
||||||
|
};
|
||||||
|
use actix_web::web;
|
||||||
|
use futures::StreamExt;
|
||||||
|
use protobuf::{Message, ProtobufResult};
|
||||||
|
|
||||||
|
pub async fn parse_from_payload<T: Message>(payload: web::Payload) -> Result<T, ServerError> {
|
||||||
|
let bytes = poll_payload(payload).await?;
|
||||||
|
parse_from_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_from_bytes<T: Message>(bytes: &[u8]) -> Result<T, ServerError> {
|
||||||
|
let result: ProtobufResult<T> = Message::parse_from_bytes(&bytes);
|
||||||
|
match result {
|
||||||
|
Ok(data) => Ok(data),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn poll_payload(mut payload: web::Payload) -> Result<web::BytesMut, ServerError> {
|
||||||
|
let mut body = web::BytesMut::new();
|
||||||
|
while let Some(chunk) = payload.next().await {
|
||||||
|
let chunk = chunk.map_err(|e| ServerError::InternalError(format!("{:?}", e)))?;
|
||||||
|
if (body.len() + chunk.len()) > MAX_PAYLOAD_SIZE {
|
||||||
|
let resp = ServerResponse::from_msg("Payload overflow", ServerCode::PayloadOverflow);
|
||||||
|
return Err(ServerError::BadRequest(resp));
|
||||||
|
}
|
||||||
|
body.extend_from_slice(&chunk);
|
||||||
|
}
|
||||||
|
Ok(body)
|
||||||
|
}
|
@ -1,3 +1,6 @@
|
|||||||
|
mod helper;
|
||||||
|
mod user;
|
||||||
pub(crate) mod ws;
|
pub(crate) mod ws;
|
||||||
|
|
||||||
|
pub use user::*;
|
||||||
pub use ws::*;
|
pub use ws::*;
|
||||||
|
23
backend/src/routers/user.rs
Normal file
23
backend/src/routers/user.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::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 std::sync::Arc;
|
||||||
|
|
||||||
|
pub async fn user_register(
|
||||||
|
request: HttpRequest,
|
||||||
|
payload: Payload,
|
||||||
|
auth: Data<Arc<Auth>>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let request: SignUpRequest = parse_from_payload(payload).await?;
|
||||||
|
// ProtobufError
|
||||||
|
let resp = ServerResponse::success();
|
||||||
|
Ok(resp.into())
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use crate::ws_service::{entities::SessionId, WSClient, WSServer};
|
use crate::ws_service::{entities::SessionId, WSClient, WSServer};
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use actix_http::{body::Body, Response};
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
get,
|
get,
|
||||||
web::{Data, Path, Payload},
|
web::{Data, Path, Payload},
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
use crate::{context::AppContext, routers::*, ws_service::WSServer};
|
use crate::{
|
||||||
|
config::Config,
|
||||||
|
context::AppContext,
|
||||||
|
routers::*,
|
||||||
|
user_service::Auth,
|
||||||
|
ws_service::WSServer,
|
||||||
|
};
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
use actix_web::{dev::Server, middleware, web, App, HttpServer, Scope};
|
use actix_web::{dev::Server, middleware, web, App, HttpServer, Scope};
|
||||||
|
use sqlx::PgPool;
|
||||||
use std::{net::TcpListener, sync::Arc};
|
use std::{net::TcpListener, sync::Arc};
|
||||||
|
|
||||||
pub fn run(app_ctx: Arc<AppContext>, listener: TcpListener) -> Result<Server, std::io::Error> {
|
pub fn run(app_ctx: Arc<AppContext>, listener: TcpListener) -> Result<Server, std::io::Error> {
|
||||||
@ -9,7 +16,9 @@ pub fn run(app_ctx: Arc<AppContext>, listener: TcpListener) -> Result<Server, st
|
|||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
.data(web::JsonConfig::default().limit(4096))
|
.data(web::JsonConfig::default().limit(4096))
|
||||||
.service(ws_scope())
|
.service(ws_scope())
|
||||||
.data(app_ctx.ws_server())
|
.data(app_ctx.ws_server.clone())
|
||||||
|
.data(app_ctx.db_pool.clone())
|
||||||
|
.data(app_ctx.auth.clone())
|
||||||
})
|
})
|
||||||
.listen(listener)?
|
.listen(listener)?
|
||||||
.run();
|
.run();
|
||||||
@ -20,7 +29,17 @@ fn ws_scope() -> Scope { web::scope("/ws").service(ws::start_connection) }
|
|||||||
|
|
||||||
pub async fn init_app_context() -> Arc<AppContext> {
|
pub async fn init_app_context() -> Arc<AppContext> {
|
||||||
let _ = flowy_log::Builder::new("flowy").env_filter("Debug").build();
|
let _ = flowy_log::Builder::new("flowy").env_filter("Debug").build();
|
||||||
|
let config = Arc::new(Config::new());
|
||||||
|
|
||||||
|
// TODO: what happened when PgPool connect fail?
|
||||||
|
let db_pool = Arc::new(
|
||||||
|
PgPool::connect(&config.database.connect_url())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to Postgres."),
|
||||||
|
);
|
||||||
let ws_server = WSServer::new().start();
|
let ws_server = WSServer::new().start();
|
||||||
let ctx = AppContext::new(ws_server);
|
let auth = Arc::new(Auth::new(db_pool.clone()));
|
||||||
|
|
||||||
|
let ctx = AppContext::new(config, ws_server, db_pool, auth);
|
||||||
Arc::new(ctx)
|
Arc::new(ctx)
|
||||||
}
|
}
|
||||||
|
14
backend/src/user_service/auth.rs
Normal file
14
backend/src/user_service/auth.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::ServerError;
|
||||||
|
use flowy_user::protobuf::SignUpRequest;
|
||||||
|
use sqlx::PgPool;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct Auth {
|
||||||
|
db_pool: Arc<PgPool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Auth {
|
||||||
|
pub fn new(db_pool: Arc<PgPool>) -> Self { Self { db_pool } }
|
||||||
|
|
||||||
|
pub fn handle_sign_up(&self, request: SignUpRequest) -> Result<(), ServerError> { Ok(()) }
|
||||||
|
}
|
3
backend/src/user_service/mod.rs
Normal file
3
backend/src/user_service/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod auth;
|
||||||
|
|
||||||
|
pub use auth::*;
|
@ -16,7 +16,6 @@ use actix::{
|
|||||||
AsyncContext,
|
AsyncContext,
|
||||||
ContextFutureSpawner,
|
ContextFutureSpawner,
|
||||||
Handler,
|
Handler,
|
||||||
Recipient,
|
|
||||||
Running,
|
Running,
|
||||||
StreamHandler,
|
StreamHandler,
|
||||||
WrapFuture,
|
WrapFuture,
|
||||||
|
@ -3,7 +3,6 @@ use crate::{
|
|||||||
ws_service::{
|
ws_service::{
|
||||||
entities::{Connect, Disconnect, Session, SessionId},
|
entities::{Connect, Disconnect, Session, SessionId},
|
||||||
ClientMessage,
|
ClientMessage,
|
||||||
WSClient,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use actix::{Actor, Context, Handler};
|
use actix::{Actor, Context, Handler};
|
||||||
|
@ -24,7 +24,7 @@ impl Builder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local(mut self, directory: impl AsRef<Path>) -> Self {
|
pub fn local(self, directory: impl AsRef<Path>) -> Self {
|
||||||
let directory = directory.as_ref().to_str().unwrap().to_owned();
|
let directory = directory.as_ref().to_str().unwrap().to_owned();
|
||||||
let local_file_name = format!("{}.log", &self.name);
|
let local_file_name = format!("{}.log", &self.name);
|
||||||
let file_appender = tracing_appender::rolling::daily(directory, local_file_name);
|
let file_appender = tracing_appender::rolling::daily(directory, local_file_name);
|
||||||
|
@ -3,7 +3,7 @@ pub mod errors;
|
|||||||
pub mod event;
|
pub mod event;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
mod protobuf;
|
pub mod protobuf;
|
||||||
mod services;
|
mod services;
|
||||||
pub mod sql_tables;
|
pub mod sql_tables;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user