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.

96 lines
2.6 KiB

  1. use diesel::prelude::*;
  2. use crate::errors;
  3. use crate::models;
  4. use bcrypt::{hash, verify, DEFAULT_COST};
  5. use std::rc::Rc;
  6. pub fn find_user_by_uid(
  7. uid: i32,
  8. conn: &SqliteConnection,
  9. ) -> Result<Option<models::UserDTO>, errors::DomainError> {
  10. use crate::schema::users::dsl::*;
  11. let maybe_user = users
  12. .select((name, created_at))
  13. .find(uid)
  14. .first::<models::UserDTO>(conn)
  15. .optional();
  16. Ok(maybe_user?)
  17. }
  18. pub fn _find_user_by_name(
  19. user_name: String,
  20. conn: &SqliteConnection,
  21. ) -> Result<Option<models::UserDTO>, errors::DomainError> {
  22. let maybe_user = query::_get_user_by_name(&user_name)
  23. .first::<models::UserDTO>(conn)
  24. .optional();
  25. Ok(maybe_user?)
  26. }
  27. pub fn get_all(
  28. conn: &SqliteConnection,
  29. ) -> Result<Option<Vec<models::UserDTO>>, errors::DomainError> {
  30. use crate::schema::users::dsl::*;
  31. Ok(users
  32. .select((name, created_at))
  33. .load::<models::UserDTO>(conn)
  34. .optional()?)
  35. }
  36. /// Run query using Diesel to insert a new database row and return the result.
  37. pub fn insert_new_user(
  38. nu: models::NewUser,
  39. conn: &SqliteConnection,
  40. ) -> Result<models::UserDTO, errors::DomainError> {
  41. // It is common when using Diesel with Actix web to import schema-related
  42. // modules inside a function's scope (rather than the normal module's scope)
  43. // to prevent import collisions and namespace pollution.
  44. use crate::schema::users::dsl::*;
  45. let nu = {
  46. let mut nu2 = nu.clone();
  47. nu2.password = hash(&nu2.password, DEFAULT_COST)?;
  48. nu2
  49. };
  50. diesel::insert_into(users).values(&nu).execute(conn)?;
  51. let user =
  52. query::_get_user_by_name(&nu.name).first::<models::UserDTO>(conn)?;
  53. Ok(user)
  54. }
  55. pub fn verify_password<'a>(
  56. user_name: &'a String,
  57. given_password: &'a String,
  58. conn: &SqliteConnection,
  59. ) -> Result<bool, errors::DomainError> {
  60. use crate::schema::users::dsl::*;
  61. let password_hash = users
  62. .select(password)
  63. .filter(name.eq(user_name))
  64. .first::<String>(conn)?;
  65. Ok(verify(given_password, password_hash.as_str())?)
  66. }
  67. mod query {
  68. use diesel::prelude::*;
  69. use diesel::sql_types::Text;
  70. use diesel::sql_types::Timestamp;
  71. use diesel::sqlite::Sqlite;
  72. /// <'a, B, T> where a = lifetime, B = Backend, T = SQL data types
  73. type Query<'a, B, T> = crate::schema::users::BoxedQuery<'a, B, T>;
  74. pub fn _get_user_by_name(
  75. user_name: &String,
  76. ) -> Query<Sqlite, (Text, Timestamp)> {
  77. use crate::schema::users::dsl::*;
  78. users
  79. .select((name, created_at))
  80. .filter(name.eq(user_name))
  81. .into_boxed()
  82. }
  83. }