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.

101 lines
2.9 KiB

  1. use diesel::prelude::*;
  2. use crate::models;
  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: i32,
  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. pub fn insert_new_user(
  38. nu: models::NewUser,
  39. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  40. hash_cost: Option<u32>,
  41. ) -> Result<models::User, errors::DomainError> {
  42. use crate::schema::users::dsl::*;
  43. let nu = {
  44. let mut nu2 = nu;
  45. let hash =
  46. hash(&nu2.password.as_str(), hash_cost.unwrap_or(DEFAULT_COST))?;
  47. nu2.password = Password::parse_string(hash).map_err(|err| {
  48. errors::DomainError::new_field_validation_error(err.to_string())
  49. })?;
  50. nu2
  51. };
  52. diesel::insert_into(users).values(&nu).execute(conn)?;
  53. let user = query::_get_user_by_name()
  54. .filter(name.eq(nu.name.as_str()))
  55. .first::<models::User>(conn)?;
  56. Ok(user)
  57. }
  58. //TODO: Add newtype here
  59. pub fn verify_password(
  60. user_name: &str,
  61. given_password: &str,
  62. conn: &impl diesel::Connection<Backend = diesel::sqlite::Sqlite>,
  63. ) -> Result<bool, errors::DomainError> {
  64. use crate::schema::users::dsl::*;
  65. let password_hash = users
  66. .select(password)
  67. .filter(name.eq(user_name))
  68. .first::<String>(conn)?;
  69. Ok(verify(given_password, password_hash.as_str())?)
  70. }
  71. mod query {
  72. use diesel::prelude::*;
  73. use diesel::sql_types::Integer;
  74. use diesel::sql_types::Text;
  75. use diesel::sql_types::Timestamp;
  76. use diesel::sqlite::Sqlite;
  77. /// <'a, B, T> where a = lifetime, B = Backend, T = SQL data types
  78. type Query<'a, B, T> = crate::schema::users::BoxedQuery<'a, B, T>;
  79. pub fn _get_user_by_name(
  80. ) -> Query<'static, Sqlite, (Integer, Text, Text, Timestamp)> {
  81. use crate::schema::users::dsl::*;
  82. users
  83. .select(users::all_columns())
  84. // .filter(name.eq(user_name))
  85. .into_boxed()
  86. }
  87. }