mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
check params using flowy-user entities
This commit is contained in:
parent
f05f0c43a3
commit
d6c761917b
@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
use chrono::{Duration, Local};
|
||||
use derive_more::{From, Into};
|
||||
use flowy_net::errors::{Code, ServerError};
|
||||
use flowy_net::errors::{ErrorCode, ServerError};
|
||||
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -51,7 +51,7 @@ impl Token {
|
||||
&EncodingKey::from_secret(jwt_secret().as_ref()),
|
||||
)
|
||||
.map(Into::into)
|
||||
.map_err(|err| ServerError::internal().with_msg(err))
|
||||
.map_err(|err| ServerError::internal().context(err))
|
||||
}
|
||||
|
||||
pub fn decode_token(token: &Self) -> Result<Claim, ServerError> {
|
||||
@ -61,6 +61,6 @@ impl Token {
|
||||
&Validation::new(DEFAULT_ALGORITHM),
|
||||
)
|
||||
.map(|data| Ok(data.claims))
|
||||
.map_err(|err| ServerError::unauthorized().with_msg(err))?
|
||||
.map_err(|err| ServerError::unauthorized().context(err))?
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::config::MAX_PAYLOAD_SIZE;
|
||||
use actix_web::web;
|
||||
use flowy_net::{
|
||||
errors::{Code, ServerError},
|
||||
errors::{ErrorCode, ServerError},
|
||||
response::*,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
@ -23,11 +23,11 @@ pub fn parse_from_bytes<T: Message>(bytes: &[u8]) -> Result<T, ServerError> {
|
||||
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(|err| ServerError::internal().with_msg(err))?;
|
||||
let chunk = chunk.map_err(|err| ServerError::internal().context(err))?;
|
||||
|
||||
if (body.len() + chunk.len()) > MAX_PAYLOAD_SIZE {
|
||||
return Err(ServerError {
|
||||
code: Code::PayloadOverflow,
|
||||
code: ErrorCode::PayloadOverflow,
|
||||
msg: "Payload overflow".to_string(),
|
||||
});
|
||||
}
|
||||
|
@ -6,11 +6,12 @@ use actix_identity::Identity;
|
||||
use anyhow::Context;
|
||||
use chrono::Utc;
|
||||
use flowy_net::{
|
||||
errors::{Code, ServerError},
|
||||
errors::{ErrorCode, ServerError},
|
||||
response::FlowyResponse,
|
||||
};
|
||||
use flowy_user::{
|
||||
entities::{SignInResponse, SignUpResponse},
|
||||
prelude::parser::{UserEmail, UserPassword},
|
||||
protobuf::{SignInParams, SignUpParams},
|
||||
};
|
||||
use sqlx::{Error, PgPool, Postgres, Transaction};
|
||||
@ -21,17 +22,23 @@ pub async fn sign_in(
|
||||
params: SignInParams,
|
||||
id: Identity,
|
||||
) -> Result<FlowyResponse, ServerError> {
|
||||
let email =
|
||||
UserEmail::parse(params.email).map_err(|e| ServerError::params_invalid().context(e))?;
|
||||
let password = UserPassword::parse(params.password)
|
||||
.map_err(|e| ServerError::params_invalid().context(e))?;
|
||||
|
||||
let mut transaction = pool
|
||||
.begin()
|
||||
.await
|
||||
.context("Failed to acquire a Postgres connection to sign in")?;
|
||||
let user = read_user(&mut transaction, ¶ms.email).await?;
|
||||
|
||||
let user = read_user(&mut transaction, &email.0).await?;
|
||||
transaction
|
||||
.commit()
|
||||
.await
|
||||
.context("Failed to commit SQL transaction to sign in.")?;
|
||||
|
||||
match verify_password(¶ms.password, &user.password) {
|
||||
match verify_password(&password.0, &user.password) {
|
||||
Ok(true) => {
|
||||
let token = Token::create_token(&user)?;
|
||||
let data = SignInResponse {
|
||||
@ -43,7 +50,7 @@ pub async fn sign_in(
|
||||
id.remember(data.token.clone());
|
||||
FlowyResponse::success(data)
|
||||
},
|
||||
_ => Err(ServerError::passwordNotMatch()),
|
||||
_ => Err(ServerError::password_not_match()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,11 +84,11 @@ async fn is_email_exist(
|
||||
.bind(email)
|
||||
.fetch_optional(transaction)
|
||||
.await
|
||||
.map_err(|err| ServerError::internal().with_msg(err))?;
|
||||
.map_err(|err| ServerError::internal().context(err))?;
|
||||
|
||||
match result {
|
||||
Some(_) => Err(ServerError {
|
||||
code: Code::EmailAlreadyExists,
|
||||
code: ErrorCode::EmailAlreadyExists,
|
||||
msg: format!("{} already exists", email),
|
||||
}),
|
||||
None => Ok(()),
|
||||
@ -96,7 +103,7 @@ async fn read_user(
|
||||
.bind(email)
|
||||
.fetch_one(transaction)
|
||||
.await
|
||||
.map_err(|err| ServerError::internal().with_msg(err))?;
|
||||
.map_err(|err| ServerError::internal().context(err))?;
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
@ -120,7 +127,7 @@ async fn insert_user(
|
||||
)
|
||||
.execute(transaction)
|
||||
.await
|
||||
.map_err(|e| ServerError::internal().with_msg(e))?;
|
||||
.map_err(|e| ServerError::internal().context(e))?;
|
||||
|
||||
let data = SignUpResponse {
|
||||
uid: uuid.to_string(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
use bcrypt::{hash, verify, BcryptError, DEFAULT_COST};
|
||||
use flowy_net::errors::{Code, ServerError};
|
||||
use flowy_net::errors::{ErrorCode, ServerError};
|
||||
use jsonwebtoken::Algorithm;
|
||||
|
||||
pub fn uuid() -> String { uuid::Uuid::new_v4().to_string() }
|
||||
@ -10,14 +10,14 @@ pub fn hash_password(plain: &str) -> Result<String, ServerError> {
|
||||
.and_then(|c| c.parse().ok())
|
||||
.unwrap_or(DEFAULT_COST);
|
||||
|
||||
hash(plain, hashing_cost).map_err(|e| ServerError::internal().with_msg(e))
|
||||
hash(plain, hashing_cost).map_err(|e| ServerError::internal().context(e))
|
||||
}
|
||||
|
||||
pub fn verify_password(source: &str, hash: &str) -> Result<bool, ServerError> {
|
||||
match verify(source, hash) {
|
||||
Ok(true) => Ok(true),
|
||||
_ => Err(ServerError {
|
||||
code: Code::PasswordNotMatch,
|
||||
code: ErrorCode::PasswordNotMatch,
|
||||
msg: "Username and password don't match".to_string(),
|
||||
}),
|
||||
}
|
||||
|
@ -4,4 +4,5 @@ pub const HOST: &'static str = "http://localhost:8000";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SIGN_UP_URL: String = format!("{}/api/register", HOST);
|
||||
pub static ref SIGN_IN_URL: String = format!("{}/api/auth", HOST);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::response::FlowyResponse;
|
||||
|
||||
#[derive(thiserror::Error, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ServerError {
|
||||
pub code: Code,
|
||||
pub code: ErrorCode,
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
@ -24,13 +24,14 @@ macro_rules! static_error {
|
||||
}
|
||||
|
||||
impl ServerError {
|
||||
static_error!(internal, Code::InternalError);
|
||||
static_error!(http, Code::HttpError);
|
||||
static_error!(payload_none, Code::PayloadUnexpectedNone);
|
||||
static_error!(unauthorized, Code::Unauthorized);
|
||||
static_error!(passwordNotMatch, Code::PasswordNotMatch);
|
||||
static_error!(internal, ErrorCode::InternalError);
|
||||
static_error!(http, ErrorCode::HttpError);
|
||||
static_error!(payload_none, ErrorCode::PayloadUnexpectedNone);
|
||||
static_error!(unauthorized, ErrorCode::Unauthorized);
|
||||
static_error!(password_not_match, ErrorCode::PasswordNotMatch);
|
||||
static_error!(params_invalid, ErrorCode::ParamsInvalid);
|
||||
|
||||
pub fn with_msg<T: Debug>(mut self, error: T) -> Self {
|
||||
pub fn context<T: Debug>(mut self, error: T) -> Self {
|
||||
self.msg = format!("{:?}", error);
|
||||
self
|
||||
}
|
||||
@ -54,7 +55,7 @@ impl std::convert::From<&ServerError> for FlowyResponse {
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone, derive_more::Display)]
|
||||
#[repr(u16)]
|
||||
pub enum Code {
|
||||
pub enum ErrorCode {
|
||||
#[display(fmt = "Token is invalid")]
|
||||
InvalidToken = 1,
|
||||
#[display(fmt = "Unauthorized")]
|
||||
@ -65,6 +66,8 @@ pub enum Code {
|
||||
PayloadSerdeFail = 4,
|
||||
#[display(fmt = "Unexpected empty payload")]
|
||||
PayloadUnexpectedNone = 5,
|
||||
#[display(fmt = "Params is invalid")]
|
||||
ParamsInvalid = 6,
|
||||
|
||||
#[display(fmt = "Protobuf serde error")]
|
||||
ProtobufError = 10,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
errors::{Code, ServerError},
|
||||
errors::{ErrorCode, ServerError},
|
||||
response::FlowyResponse,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
@ -83,7 +83,7 @@ impl HttpRequestBuilder {
|
||||
match data {
|
||||
None => {
|
||||
let msg = format!("Request: {} receives unexpected empty body", self.url);
|
||||
Err(ServerError::payload_none().with_msg(msg))
|
||||
Err(ServerError::payload_none().context(msg))
|
||||
},
|
||||
Some(data) => Ok(T2::try_from(data)?),
|
||||
}
|
||||
@ -121,7 +121,7 @@ async fn get_response_data(original: Response) -> Result<Bytes, ServerError> {
|
||||
Some(error) => Err(error),
|
||||
}
|
||||
} else {
|
||||
Err(ServerError::http().with_msg(original))
|
||||
Err(ServerError::http().context(original))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::errors::{Code, ServerError};
|
||||
use crate::errors::{ErrorCode, ServerError};
|
||||
use bytes::Bytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{convert::TryInto, error::Error, fmt::Debug};
|
||||
@ -25,35 +25,35 @@ impl FlowyResponse {
|
||||
impl std::convert::From<protobuf::ProtobufError> for ServerError {
|
||||
fn from(err: protobuf::ProtobufError) -> Self {
|
||||
ServerError {
|
||||
code: Code::ProtobufError,
|
||||
code: ErrorCode::ProtobufError,
|
||||
msg: format!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<RecvError> for ServerError {
|
||||
fn from(error: RecvError) -> Self { ServerError::internal().with_msg(error) }
|
||||
fn from(error: RecvError) -> Self { ServerError::internal().context(error) }
|
||||
}
|
||||
|
||||
impl std::convert::From<serde_json::Error> for ServerError {
|
||||
fn from(e: serde_json::Error) -> Self {
|
||||
let msg = format!("Serial error: {:?}", e);
|
||||
ServerError {
|
||||
code: Code::SerdeError,
|
||||
code: ErrorCode::SerdeError,
|
||||
msg,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<anyhow::Error> for ServerError {
|
||||
fn from(error: anyhow::Error) -> Self { ServerError::internal().with_msg(error) }
|
||||
fn from(error: anyhow::Error) -> Self { ServerError::internal().context(error) }
|
||||
}
|
||||
|
||||
impl std::convert::From<reqwest::Error> for ServerError {
|
||||
fn from(error: reqwest::Error) -> Self {
|
||||
if error.is_timeout() {
|
||||
return ServerError {
|
||||
code: Code::ConnectTimeout,
|
||||
code: ErrorCode::ConnectTimeout,
|
||||
msg: format!("{}", error),
|
||||
};
|
||||
}
|
||||
@ -62,22 +62,22 @@ impl std::convert::From<reqwest::Error> for ServerError {
|
||||
let hyper_error: Option<&hyper::Error> = error.source().unwrap().downcast_ref();
|
||||
return match hyper_error {
|
||||
None => ServerError {
|
||||
code: Code::ConnectRefused,
|
||||
code: ErrorCode::ConnectRefused,
|
||||
msg: format!("{:?}", error),
|
||||
},
|
||||
Some(hyper_error) => {
|
||||
let mut code = Code::InternalError;
|
||||
let mut code = ErrorCode::InternalError;
|
||||
let msg = format!("{}", error);
|
||||
if hyper_error.is_closed() {
|
||||
code = Code::ConnectClose;
|
||||
code = ErrorCode::ConnectClose;
|
||||
}
|
||||
|
||||
if hyper_error.is_connect() {
|
||||
code = Code::ConnectRefused;
|
||||
code = ErrorCode::ConnectRefused;
|
||||
}
|
||||
|
||||
if hyper_error.is_canceled() {
|
||||
code = Code::ConnectCancel;
|
||||
code = ErrorCode::ConnectCancel;
|
||||
}
|
||||
|
||||
if hyper_error.is_timeout() {}
|
||||
@ -89,7 +89,7 @@ impl std::convert::From<reqwest::Error> for ServerError {
|
||||
|
||||
let msg = format!("{:?}", error);
|
||||
ServerError {
|
||||
code: Code::ProtobufError,
|
||||
code: ErrorCode::ProtobufError,
|
||||
msg,
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ pub use sign_in::*;
|
||||
pub use sign_up::*;
|
||||
pub use user_detail::*;
|
||||
pub use user_update::*;
|
||||
mod parser;
|
||||
pub mod parser;
|
||||
mod sign_in;
|
||||
pub mod sign_up;
|
||||
mod user_detail;
|
||||
|
@ -63,6 +63,7 @@ pub enum UserErrCode {
|
||||
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")]
|
||||
@ -83,6 +84,10 @@ pub enum UserErrCode {
|
||||
NetworkError = 100,
|
||||
}
|
||||
|
||||
impl UserErrCode {
|
||||
pub fn to_string(&self) -> String { format!("{}", self) }
|
||||
}
|
||||
|
||||
impl std::default::Default for UserErrCode {
|
||||
fn default() -> Self { UserErrCode::Unknown }
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use flowy_net::{
|
||||
config::SIGN_UP_URL,
|
||||
config::*,
|
||||
future::ResultFuture,
|
||||
request::{http_post, HttpRequestBuilder},
|
||||
};
|
||||
@ -35,15 +35,8 @@ impl UserServer for UserServerImpl {
|
||||
ResultFuture::new(async move { user_sign_up(params, SIGN_UP_URL.as_ref()).await })
|
||||
}
|
||||
|
||||
fn sign_in(&self, _params: SignInParams) -> ResultFuture<SignInResponse, UserError> {
|
||||
// let user_id = params.email.clone();
|
||||
// Ok(UserTable::new(
|
||||
// user_id,
|
||||
// "".to_owned(),
|
||||
// params.email,
|
||||
// params.password,
|
||||
// ))
|
||||
unimplemented!()
|
||||
fn sign_in(&self, params: SignInParams) -> ResultFuture<SignInResponse, UserError> {
|
||||
ResultFuture::new(async move { user_sign_in(params, SIGN_IN_URL.as_ref()).await })
|
||||
}
|
||||
|
||||
fn sign_out(&self, _user_id: &str) -> ResultFuture<(), UserError> {
|
||||
|
Loading…
Reference in New Issue
Block a user