2021-08-23 18:39:10 +08:00
|
|
|
use crate::{
|
2021-08-24 21:38:53 +08:00
|
|
|
entities::{token::Token, user::UserTable},
|
2021-08-24 13:10:53 +08:00
|
|
|
user_service::{hash_password, verify_password},
|
2021-08-23 18:39:10 +08:00
|
|
|
};
|
|
|
|
use actix_identity::Identity;
|
|
|
|
use anyhow::Context;
|
|
|
|
use chrono::Utc;
|
|
|
|
use flowy_net::{
|
2021-08-25 17:34:20 +08:00
|
|
|
errors::{ErrorCode, ServerError},
|
2021-08-23 18:39:10 +08:00
|
|
|
response::FlowyResponse,
|
|
|
|
};
|
|
|
|
use flowy_user::{
|
2021-08-24 13:10:53 +08:00
|
|
|
entities::{parser::UserName, SignInResponse, SignUpResponse},
|
2021-08-23 23:02:42 +08:00
|
|
|
prelude::parser::{UserEmail, UserPassword},
|
2021-08-23 18:39:10 +08:00
|
|
|
protobuf::{SignInParams, SignUpParams},
|
|
|
|
};
|
2021-08-26 10:19:50 +08:00
|
|
|
use sqlx::{PgPool, Postgres, Transaction};
|
2021-08-23 18:39:10 +08:00
|
|
|
|
|
|
|
pub async fn sign_in(
|
|
|
|
pool: &PgPool,
|
|
|
|
params: SignInParams,
|
|
|
|
id: Identity,
|
|
|
|
) -> Result<FlowyResponse, ServerError> {
|
2021-08-23 23:02:42 +08:00
|
|
|
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))?;
|
|
|
|
|
2021-08-23 18:39:10 +08:00
|
|
|
let mut transaction = pool
|
|
|
|
.begin()
|
|
|
|
.await
|
|
|
|
.context("Failed to acquire a Postgres connection to sign in")?;
|
2021-08-23 23:02:42 +08:00
|
|
|
|
|
|
|
let user = read_user(&mut transaction, &email.0).await?;
|
2021-08-23 18:39:10 +08:00
|
|
|
transaction
|
|
|
|
.commit()
|
|
|
|
.await
|
|
|
|
.context("Failed to commit SQL transaction to sign in.")?;
|
|
|
|
|
2021-08-23 23:02:42 +08:00
|
|
|
match verify_password(&password.0, &user.password) {
|
2021-08-23 18:39:10 +08:00
|
|
|
Ok(true) => {
|
|
|
|
let token = Token::create_token(&user)?;
|
|
|
|
let data = SignInResponse {
|
|
|
|
uid: user.id.to_string(),
|
|
|
|
name: user.name,
|
|
|
|
email: user.email,
|
|
|
|
token: token.into(),
|
|
|
|
};
|
|
|
|
id.remember(data.token.clone());
|
2021-08-24 21:38:53 +08:00
|
|
|
FlowyResponse::success().data(data)
|
2021-08-23 18:39:10 +08:00
|
|
|
},
|
2021-08-23 23:02:42 +08:00
|
|
|
_ => Err(ServerError::password_not_match()),
|
2021-08-23 18:39:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn register_user(
|
|
|
|
pool: &PgPool,
|
|
|
|
params: SignUpParams,
|
|
|
|
) -> Result<FlowyResponse, ServerError> {
|
2021-08-24 13:10:53 +08:00
|
|
|
let name =
|
|
|
|
UserName::parse(params.name).map_err(|e| ServerError::params_invalid().context(e))?;
|
|
|
|
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))?;
|
|
|
|
|
2021-08-23 18:39:10 +08:00
|
|
|
let mut transaction = pool
|
|
|
|
.begin()
|
|
|
|
.await
|
|
|
|
.context("Failed to acquire a Postgres connection to register user")?;
|
|
|
|
|
2021-08-24 13:10:53 +08:00
|
|
|
let _ = is_email_exist(&mut transaction, email.as_ref()).await?;
|
|
|
|
let data = insert_user(
|
|
|
|
&mut transaction,
|
|
|
|
name.as_ref(),
|
|
|
|
email.as_ref(),
|
|
|
|
password.as_ref(),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.context("Failed to insert user")?;
|
2021-08-23 18:39:10 +08:00
|
|
|
|
|
|
|
transaction
|
|
|
|
.commit()
|
|
|
|
.await
|
|
|
|
.context("Failed to commit SQL transaction to register user.")?;
|
|
|
|
|
2021-08-24 21:38:53 +08:00
|
|
|
FlowyResponse::success().data(data)
|
2021-08-23 18:39:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn is_email_exist(
|
|
|
|
transaction: &mut Transaction<'_, Postgres>,
|
|
|
|
email: &str,
|
|
|
|
) -> Result<(), ServerError> {
|
|
|
|
let result = sqlx::query(r#"SELECT email FROM user_table WHERE email = $1"#)
|
|
|
|
.bind(email)
|
|
|
|
.fetch_optional(transaction)
|
|
|
|
.await
|
2021-08-23 23:02:42 +08:00
|
|
|
.map_err(|err| ServerError::internal().context(err))?;
|
2021-08-23 18:39:10 +08:00
|
|
|
|
|
|
|
match result {
|
|
|
|
Some(_) => Err(ServerError {
|
2021-08-23 23:02:42 +08:00
|
|
|
code: ErrorCode::EmailAlreadyExists,
|
2021-08-23 18:39:10 +08:00
|
|
|
msg: format!("{} already exists", email),
|
|
|
|
}),
|
|
|
|
None => Ok(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn read_user(
|
|
|
|
transaction: &mut Transaction<'_, Postgres>,
|
|
|
|
email: &str,
|
2021-08-24 21:38:53 +08:00
|
|
|
) -> Result<UserTable, ServerError> {
|
|
|
|
let user = sqlx::query_as::<Postgres, UserTable>("SELECT * FROM user_table WHERE email = $1")
|
2021-08-23 18:39:10 +08:00
|
|
|
.bind(email)
|
|
|
|
.fetch_one(transaction)
|
|
|
|
.await
|
2021-08-23 23:02:42 +08:00
|
|
|
.map_err(|err| ServerError::internal().context(err))?;
|
2021-08-23 18:39:10 +08:00
|
|
|
|
|
|
|
Ok(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn insert_user(
|
|
|
|
transaction: &mut Transaction<'_, Postgres>,
|
2021-08-24 13:10:53 +08:00
|
|
|
name: &str,
|
|
|
|
email: &str,
|
|
|
|
password: &str,
|
2021-08-23 18:39:10 +08:00
|
|
|
) -> Result<SignUpResponse, ServerError> {
|
|
|
|
let uuid = uuid::Uuid::new_v4();
|
2021-08-24 13:10:53 +08:00
|
|
|
let password = hash_password(password)?;
|
2021-08-23 18:39:10 +08:00
|
|
|
let _ = sqlx::query!(
|
|
|
|
r#"
|
|
|
|
INSERT INTO user_table (id, email, name, create_time, password)
|
|
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
|
|
"#,
|
|
|
|
uuid,
|
2021-08-24 13:10:53 +08:00
|
|
|
email,
|
|
|
|
name,
|
2021-08-23 18:39:10 +08:00
|
|
|
Utc::now(),
|
2021-08-23 22:10:36 +08:00
|
|
|
password,
|
2021-08-23 18:39:10 +08:00
|
|
|
)
|
|
|
|
.execute(transaction)
|
|
|
|
.await
|
2021-08-23 23:02:42 +08:00
|
|
|
.map_err(|e| ServerError::internal().context(e))?;
|
2021-08-23 18:39:10 +08:00
|
|
|
|
|
|
|
let data = SignUpResponse {
|
|
|
|
uid: uuid.to_string(),
|
2021-08-24 13:10:53 +08:00
|
|
|
name: name.to_string(),
|
|
|
|
email: email.to_string(),
|
2021-08-23 18:39:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(data)
|
|
|
|
}
|