2021-08-23 18:39:10 +08:00
|
|
|
use crate::{
|
|
|
|
entities::{token::Token, user::User},
|
|
|
|
user_service::utils::{hash_password, verify_password},
|
|
|
|
};
|
|
|
|
use actix_identity::Identity;
|
|
|
|
use anyhow::Context;
|
|
|
|
use chrono::Utc;
|
|
|
|
use flowy_net::{
|
2021-08-23 23:02:42 +08:00
|
|
|
errors::{ErrorCode, ServerError},
|
2021-08-23 18:39:10 +08:00
|
|
|
response::FlowyResponse,
|
|
|
|
};
|
|
|
|
use flowy_user::{
|
|
|
|
entities::{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},
|
|
|
|
};
|
|
|
|
use sqlx::{Error, PgPool, Postgres, Transaction};
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
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());
|
|
|
|
FlowyResponse::success(data)
|
|
|
|
},
|
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> {
|
|
|
|
let mut transaction = pool
|
|
|
|
.begin()
|
|
|
|
.await
|
|
|
|
.context("Failed to acquire a Postgres connection to register user")?;
|
|
|
|
|
|
|
|
let _ = is_email_exist(&mut transaction, ¶ms.email).await?;
|
|
|
|
let data = insert_user(&mut transaction, params)
|
|
|
|
.await
|
|
|
|
.context("Failed to insert user")?;
|
|
|
|
|
|
|
|
transaction
|
|
|
|
.commit()
|
|
|
|
.await
|
|
|
|
.context("Failed to commit SQL transaction to register user.")?;
|
|
|
|
|
|
|
|
FlowyResponse::success(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
) -> Result<User, ServerError> {
|
|
|
|
let user = sqlx::query_as::<Postgres, User>("SELECT * FROM user_table WHERE email = $1")
|
|
|
|
.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>,
|
|
|
|
params: SignUpParams,
|
|
|
|
) -> Result<SignUpResponse, ServerError> {
|
|
|
|
let uuid = uuid::Uuid::new_v4();
|
|
|
|
let password = hash_password(¶ms.password)?;
|
|
|
|
let _ = sqlx::query!(
|
|
|
|
r#"
|
|
|
|
INSERT INTO user_table (id, email, name, create_time, password)
|
|
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
|
|
"#,
|
|
|
|
uuid,
|
|
|
|
params.email,
|
|
|
|
params.name,
|
|
|
|
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(),
|
|
|
|
name: params.name,
|
|
|
|
email: params.email,
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(data)
|
|
|
|
}
|