auth.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. use super::AUTHORIZED_USERS;
  2. use crate::{
  3. entities::{token::Token, user::UserTable},
  4. sqlx_ext::DBTransaction,
  5. user_service::{hash_password, verify_password, LoggedUser},
  6. workspace_service::user_default::create_default_workspace,
  7. };
  8. use crate::sqlx_ext::{map_sqlx_error, SqlBuilder};
  9. use anyhow::Context;
  10. use chrono::Utc;
  11. use flowy_net::{
  12. errors::{invalid_params, ErrorCode, ServerError},
  13. response::FlowyResponse,
  14. };
  15. use flowy_user::{
  16. entities::parser::{UserEmail, UserName, UserPassword},
  17. protobuf::{
  18. SignInParams,
  19. SignInResponse,
  20. SignUpParams,
  21. SignUpResponse,
  22. UpdateUserParams,
  23. UserProfile,
  24. },
  25. };
  26. use sqlx::{PgPool, Postgres};
  27. pub async fn sign_in(pool: &PgPool, params: SignInParams) -> Result<SignInResponse, ServerError> {
  28. let email =
  29. UserEmail::parse(params.email).map_err(|e| ServerError::params_invalid().context(e))?;
  30. let password = UserPassword::parse(params.password)
  31. .map_err(|e| ServerError::params_invalid().context(e))?;
  32. let mut transaction = pool
  33. .begin()
  34. .await
  35. .context("Failed to acquire a Postgres connection to sign in")?;
  36. let user = check_user_password(&mut transaction, email.as_ref(), password.as_ref()).await?;
  37. transaction
  38. .commit()
  39. .await
  40. .context("Failed to commit SQL transaction to sign in.")?;
  41. let token = Token::create_token(&user.id.to_string())?;
  42. let logged_user = LoggedUser::new(&user.id.to_string());
  43. let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
  44. let mut response_data = SignInResponse::default();
  45. response_data.set_uid(user.id.to_string());
  46. response_data.set_name(user.name);
  47. response_data.set_email(user.email);
  48. response_data.set_token(token.clone().into());
  49. Ok(response_data)
  50. }
  51. pub async fn sign_out(logged_user: LoggedUser) -> Result<FlowyResponse, ServerError> {
  52. let _ = AUTHORIZED_USERS.store_auth(logged_user, false)?;
  53. Ok(FlowyResponse::success())
  54. }
  55. pub async fn register_user(
  56. pool: &PgPool,
  57. params: SignUpParams,
  58. ) -> Result<FlowyResponse, ServerError> {
  59. let name =
  60. UserName::parse(params.name).map_err(|e| ServerError::params_invalid().context(e))?;
  61. let email =
  62. UserEmail::parse(params.email).map_err(|e| ServerError::params_invalid().context(e))?;
  63. let password = UserPassword::parse(params.password)
  64. .map_err(|e| ServerError::params_invalid().context(e))?;
  65. let mut transaction = pool
  66. .begin()
  67. .await
  68. .context("Failed to acquire a Postgres connection to register user")?;
  69. let _ = is_email_exist(&mut transaction, email.as_ref()).await?;
  70. let response_data = insert_new_user(
  71. &mut transaction,
  72. name.as_ref(),
  73. email.as_ref(),
  74. password.as_ref(),
  75. )
  76. .await
  77. .context("Failed to insert user")?;
  78. let logged_user = LoggedUser::new(&response_data.user_id);
  79. let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
  80. let _ = create_default_workspace(&mut transaction, response_data.get_user_id()).await?;
  81. transaction
  82. .commit()
  83. .await
  84. .context("Failed to commit SQL transaction to register user.")?;
  85. FlowyResponse::success().pb(response_data)
  86. }
  87. pub(crate) async fn get_user_profile(
  88. pool: &PgPool,
  89. logged_user: LoggedUser,
  90. ) -> Result<FlowyResponse, ServerError> {
  91. let mut transaction = pool
  92. .begin()
  93. .await
  94. .context("Failed to acquire a Postgres connection to get user detail")?;
  95. let id = logged_user.get_user_id()?;
  96. let user_table =
  97. sqlx::query_as::<Postgres, UserTable>("SELECT * FROM user_table WHERE id = $1")
  98. .bind(id)
  99. .fetch_one(&mut transaction)
  100. .await
  101. .map_err(|err| ServerError::internal().context(err))?;
  102. transaction
  103. .commit()
  104. .await
  105. .context("Failed to commit SQL transaction to get user detail.")?;
  106. // update the user active time
  107. let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
  108. let mut user_profile = UserProfile::default();
  109. user_profile.set_id(user_table.id.to_string());
  110. user_profile.set_email(user_table.email);
  111. user_profile.set_name(user_table.name);
  112. FlowyResponse::success().pb(user_profile)
  113. }
  114. pub(crate) async fn set_user_profile(
  115. pool: &PgPool,
  116. logged_user: LoggedUser,
  117. params: UpdateUserParams,
  118. ) -> Result<FlowyResponse, ServerError> {
  119. let mut transaction = pool
  120. .begin()
  121. .await
  122. .context("Failed to acquire a Postgres connection to update user profile")?;
  123. let name = match params.has_name() {
  124. false => None,
  125. true => Some(
  126. UserName::parse(params.get_name().to_owned())
  127. .map_err(invalid_params)?
  128. .0,
  129. ),
  130. };
  131. let email = match params.has_email() {
  132. false => None,
  133. true => Some(
  134. UserEmail::parse(params.get_email().to_owned())
  135. .map_err(invalid_params)?
  136. .0,
  137. ),
  138. };
  139. let password = match params.has_password() {
  140. false => None,
  141. true => {
  142. let password =
  143. UserPassword::parse(params.get_password().to_owned()).map_err(invalid_params)?;
  144. let password = hash_password(password.as_ref())?;
  145. Some(password)
  146. },
  147. };
  148. let (sql, args) = SqlBuilder::update("user_table")
  149. .add_some_arg("name", name)
  150. .add_some_arg("email", email)
  151. .add_some_arg("password", password)
  152. .and_where_eq("id", &logged_user.get_user_id()?)
  153. .build()?;
  154. sqlx::query_with(&sql, args)
  155. .execute(&mut transaction)
  156. .await
  157. .map_err(map_sqlx_error)?;
  158. transaction
  159. .commit()
  160. .await
  161. .context("Failed to commit SQL transaction to update user profile.")?;
  162. Ok(FlowyResponse::success())
  163. }
  164. async fn is_email_exist(
  165. transaction: &mut DBTransaction<'_>,
  166. email: &str,
  167. ) -> Result<(), ServerError> {
  168. let result = sqlx::query(r#"SELECT email FROM user_table WHERE email = $1"#)
  169. .bind(email)
  170. .fetch_optional(transaction)
  171. .await
  172. .map_err(|err| ServerError::internal().context(err))?;
  173. match result {
  174. Some(_) => Err(ServerError {
  175. code: ErrorCode::EmailAlreadyExists,
  176. msg: format!("{} already exists", email),
  177. }),
  178. None => Ok(()),
  179. }
  180. }
  181. async fn check_user_password(
  182. transaction: &mut DBTransaction<'_>,
  183. email: &str,
  184. password: &str,
  185. ) -> Result<UserTable, ServerError> {
  186. let user = sqlx::query_as::<Postgres, UserTable>("SELECT * FROM user_table WHERE email = $1")
  187. .bind(email)
  188. .fetch_one(transaction)
  189. .await
  190. .map_err(|err| ServerError::internal().context(err))?;
  191. match verify_password(&password, &user.password) {
  192. Ok(true) => Ok(user),
  193. _ => Err(ServerError::password_not_match()),
  194. }
  195. }
  196. async fn insert_new_user(
  197. transaction: &mut DBTransaction<'_>,
  198. name: &str,
  199. email: &str,
  200. password: &str,
  201. ) -> Result<SignUpResponse, ServerError> {
  202. let uuid = uuid::Uuid::new_v4();
  203. let token = Token::create_token(&uuid.to_string())?;
  204. let password = hash_password(password)?;
  205. let _ = sqlx::query!(
  206. r#"
  207. INSERT INTO user_table (id, email, name, create_time, password)
  208. VALUES ($1, $2, $3, $4, $5)
  209. "#,
  210. uuid,
  211. email,
  212. name,
  213. Utc::now(),
  214. password,
  215. )
  216. .execute(transaction)
  217. .await
  218. .map_err(|e| ServerError::internal().context(e))?;
  219. let mut response = SignUpResponse::default();
  220. response.set_user_id(uuid.to_string());
  221. response.set_name(name.to_string());
  222. response.set_email(email.to_string());
  223. response.set_token(token.into());
  224. Ok(response)
  225. }