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.

130 lines
3.8 KiB

  1. use serde::{Deserialize, Serialize};
  2. use crate::schema::users;
  3. use crate::utils::regex;
  4. use derive_more::{Display, Into};
  5. use std::convert::TryFrom;
  6. use std::{convert::TryInto, str::FromStr};
  7. use validators::prelude::*;
  8. #[derive(
  9. Debug,
  10. Clone,
  11. Eq,
  12. Hash,
  13. PartialEq,
  14. Deserialize,
  15. Display,
  16. Into,
  17. Serialize,
  18. DieselNewType,
  19. )]
  20. #[serde(try_from = "u32", into = "u32")]
  21. pub struct UserId(i32);
  22. impl From<UserId> for u32 {
  23. fn from(s: UserId) -> u32 {
  24. //this should be safe to unwrap since our newtype
  25. //does not allow negative values
  26. s.0.try_into().unwrap()
  27. }
  28. }
  29. impl FromStr for UserId {
  30. type Err = String;
  31. fn from_str(s: &str) -> Result<Self, Self::Err> {
  32. if let Ok(num) = s.parse::<u32>() {
  33. (num as u32)
  34. .try_into()
  35. .map_err(|err| {
  36. format!("error while converting user_id: {}", err)
  37. })
  38. .map(UserId)
  39. } else {
  40. Err("negative values are not allowed".to_owned())
  41. }
  42. }
  43. }
  44. impl TryFrom<u32> for UserId {
  45. type Error = String;
  46. fn try_from(value: u32) -> Result<Self, Self::Error> {
  47. value
  48. .try_into()
  49. .map_err(|err| format!("error while converting user_id: {}", err))
  50. .map(UserId)
  51. }
  52. }
  53. #[derive(Validator, Debug, Clone, DieselNewType)]
  54. #[validator(regex(regex::USERNAME_REG))]
  55. pub struct Username(String);
  56. impl Username {
  57. pub fn as_str(&self) -> &str {
  58. &self.0
  59. }
  60. }
  61. #[derive(Validator, Debug, Clone, DieselNewType)]
  62. #[validator(line(char_length(max = 200)))]
  63. pub struct Password(String);
  64. impl Password {
  65. pub fn as_str(&self) -> &str {
  66. &self.0
  67. }
  68. }
  69. #[derive(Debug, Clone, Deserialize, Serialize, Queryable, Identifiable)]
  70. #[table_name = "users"]
  71. pub struct User {
  72. pub id: UserId,
  73. pub name: Username,
  74. #[serde(skip_serializing)]
  75. pub password: Password,
  76. pub created_at: chrono::NaiveDateTime,
  77. }
  78. #[derive(Debug, Clone, Insertable, Deserialize)]
  79. #[table_name = "users"]
  80. pub struct NewUser {
  81. pub name: Username,
  82. #[serde(skip_serializing)]
  83. pub password: Password,
  84. }
  85. #[cfg(test)]
  86. mod test {
  87. use super::*;
  88. #[test]
  89. fn user_model_refinement_test() {
  90. //yes I had been watching a lot of star wars lately
  91. let mb_user = serde_json::from_str::<User>(
  92. r#"{"id":1,"name":"chewbacca","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  93. );
  94. // println!("{:?}", mb_user);
  95. assert_eq!(mb_user.is_ok(), true);
  96. let mb_user = serde_json::from_str::<User>(
  97. r#"{"id":1,"name":"chew-bacca","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  98. );
  99. assert_eq!(mb_user.is_ok(), true);
  100. let mb_user = serde_json::from_str::<User>(
  101. r#"{"id":1,"name":"chew.bacca","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  102. );
  103. assert_eq!(mb_user.is_ok(), false);
  104. let mb_user = serde_json::from_str::<User>(
  105. r#"{"id":-1,"name":"chewbacca","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  106. );
  107. assert_eq!(mb_user.is_ok(), false);
  108. let mb_user = serde_json::from_str::<User>(
  109. r#"{"id":1,"name":"ch","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  110. );
  111. assert_eq!(mb_user.is_ok(), false);
  112. let mb_user = serde_json::from_str::<User>(
  113. r#"{"id":1,"name":"chaegw;eaef","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  114. );
  115. assert_eq!(mb_user.is_ok(), false);
  116. let mb_user = serde_json::from_str::<User>(
  117. r#"{"id":1,"name":"chaegw_eaef","password":"aeqfq3fq","created_at":"2021-05-12T12:37:56"}"#,
  118. );
  119. assert_eq!(mb_user.is_ok(), false);
  120. }
  121. }