You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.6 KiB

  1. use diesel::prelude::*;
  2. use crate::models::{self, Pagination, UserId};
  3. use crate::{errors, models::Password};
  4. use bcrypt::{hash, verify, DEFAULT_COST};
  5. use validators::prelude::*;
  6. pub fn find_user_by_uid(
  7. uid: &UserId,
  8. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  9. ) -> Result<Option<models::User>, errors::DomainError> {
  10. use crate::schema::users::dsl::*;
  11. let maybe_user = users
  12. .select(users::all_columns())
  13. .find(uid)
  14. .first::<models::User>(conn)
  15. .optional();
  16. Ok(maybe_user?)
  17. }
  18. pub fn _find_user_by_name(
  19. user_name: String,
  20. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  21. ) -> Result<Option<models::User>, errors::DomainError> {
  22. use crate::schema::users::dsl::*;
  23. let maybe_user = query::_get_user_by_name()
  24. .filter(name.eq(user_name))
  25. .first::<models::User>(conn)
  26. .optional();
  27. Ok(maybe_user?)
  28. }
  29. pub fn get_all(
  30. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  31. ) -> Result<Vec<models::User>, errors::DomainError> {
  32. use crate::schema::users::dsl::*;
  33. Ok(users
  34. .select(users::all_columns())
  35. .load::<models::User>(conn)?)
  36. }
  37. // def findAll(userId: Long, limit: Int, offset: Int) = db.run {
  38. // for {
  39. // comments <- query.filter(_.creatorId === userId)
  40. // .sortBy(_.createdAt)
  41. // .drop(offset).take(limit)
  42. // .result
  43. // numberOfComments <- query.filter(_.creatorId === userId).length.result
  44. // } yield PaginatedResult(
  45. // totalCount = numberOfComments,
  46. // entities = comments.toList,
  47. // hasNextPage = numberOfComments - (offset + limit) > 0
  48. // )
  49. // }
  50. pub fn get_users_paginated(
  51. // user_id: UserId,
  52. pagination: &Pagination,
  53. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  54. ) -> Result<Vec<models::User>, errors::DomainError> {
  55. // use crate::schema::users::dsl::*;
  56. Ok(query::_paginate_result(&pagination).load::<models::User>(conn)?)
  57. }
  58. pub fn search_users(
  59. query: &str,
  60. pagination: &Pagination,
  61. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  62. ) -> Result<Vec<models::User>, errors::DomainError> {
  63. use crate::schema::users::dsl::*;
  64. // Ok(users
  65. // .filter(name.like(format!("%{}%", query)))
  66. // .order_by(created_at)
  67. // .offset(pagination.calc_offset().as_uint().into())
  68. // .limit(pagination.limit.as_uint().into())
  69. // .load::<models::User>(conn)?)
  70. Ok(query::_paginate_result(&pagination)
  71. .filter(name.like(format!("%{}%", query)))
  72. .load::<models::User>(conn)?)
  73. }
  74. pub fn insert_new_user(
  75. nu: models::NewUser,
  76. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  77. hash_cost: Option<u32>,
  78. ) -> Result<models::User, errors::DomainError> {
  79. use crate::schema::users::dsl::*;
  80. let nu = {
  81. let mut nu2 = nu;
  82. let hash =
  83. hash(&nu2.password.as_str(), hash_cost.unwrap_or(DEFAULT_COST))?;
  84. nu2.password = Password::parse_string(hash).map_err(|err| {
  85. errors::DomainError::new_field_validation_error(err.to_string())
  86. })?;
  87. nu2
  88. };
  89. diesel::insert_into(users).values(&nu).execute(conn)?;
  90. let user = query::_get_user_by_name()
  91. .filter(name.eq(nu.name.as_str()))
  92. .first::<models::User>(conn)?;
  93. Ok(user)
  94. }
  95. //TODO: Add newtype here
  96. pub fn verify_password(
  97. user_name: &str,
  98. given_password: &str,
  99. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  100. ) -> Result<bool, errors::DomainError> {
  101. use crate::schema::users::dsl::*;
  102. let password_hash = users
  103. .select(password)
  104. .filter(name.eq(user_name))
  105. .first::<String>(conn)?;
  106. Ok(verify(given_password, password_hash.as_str())?)
  107. }
  108. mod query {
  109. use super::*;
  110. use diesel::sql_types::Integer;
  111. use diesel::sql_types::Text;
  112. use diesel::sql_types::Timestamp;
  113. use diesel::sqlite::Sqlite;
  114. /// <'a, B, T> where a = lifetime, B = Backend, T = SQL data types
  115. type Query<'a, B, T> = crate::schema::users::BoxedQuery<'a, B, T>;
  116. pub fn _get_user_by_name(
  117. ) -> Query<'static, Sqlite, (Integer, Text, Text, Timestamp)> {
  118. use crate::schema::users::dsl::*;
  119. users.into_boxed()
  120. }
  121. pub fn _paginate_result(
  122. pagination: &Pagination,
  123. ) -> Query<'static, Sqlite, (Integer, Text, Text, Timestamp)> {
  124. use crate::schema::users::dsl::*;
  125. users
  126. .order_by(created_at)
  127. .offset(pagination.calc_offset().as_uint().into())
  128. .limit(pagination.limit.as_uint().into())
  129. .into_boxed()
  130. }
  131. }