]> Untitled Git - lemmy.git/blob - crates/db_queries/src/source/password_reset_request.rs
d04a1ac4bc39a9c3a51670320dd3fed23df7ee30
[lemmy.git] / crates / db_queries / src / source / password_reset_request.rs
1 use crate::Crud;
2 use diesel::{dsl::*, result::Error, PgConnection, *};
3 use lemmy_db_schema::{
4   schema::password_reset_request::dsl::*,
5   source::password_reset_request::*,
6   LocalUserId,
7 };
8 use sha2::{Digest, Sha256};
9
10 impl Crud<PasswordResetRequestForm, i32> for PasswordResetRequest {
11   fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
12     password_reset_request
13       .find(password_reset_request_id)
14       .first::<Self>(conn)
15   }
16   fn create(conn: &PgConnection, form: &PasswordResetRequestForm) -> Result<Self, Error> {
17     insert_into(password_reset_request)
18       .values(form)
19       .get_result::<Self>(conn)
20   }
21   fn update(
22     conn: &PgConnection,
23     password_reset_request_id: i32,
24     form: &PasswordResetRequestForm,
25   ) -> Result<Self, Error> {
26     diesel::update(password_reset_request.find(password_reset_request_id))
27       .set(form)
28       .get_result::<Self>(conn)
29   }
30 }
31
32 pub trait PasswordResetRequest_ {
33   fn create_token(
34     conn: &PgConnection,
35     from_local_user_id: LocalUserId,
36     token: &str,
37   ) -> Result<PasswordResetRequest, Error>;
38   fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error>;
39 }
40
41 impl PasswordResetRequest_ for PasswordResetRequest {
42   fn create_token(
43     conn: &PgConnection,
44     from_local_user_id: LocalUserId,
45     token: &str,
46   ) -> Result<PasswordResetRequest, Error> {
47     let mut hasher = Sha256::new();
48     hasher.update(token);
49     let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
50
51     let form = PasswordResetRequestForm {
52       local_user_id: from_local_user_id,
53       token_encrypted: token_hash,
54     };
55
56     Self::create(conn, &form)
57   }
58   fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error> {
59     let mut hasher = Sha256::new();
60     hasher.update(token);
61     let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
62     password_reset_request
63       .filter(token_encrypted.eq(token_hash))
64       .filter(published.gt(now - 1.days()))
65       .first::<Self>(conn)
66   }
67 }
68
69 fn bytes_to_hex(bytes: Vec<u8>) -> String {
70   let mut str = String::new();
71   for byte in bytes {
72     str = format!("{}{:02x}", str, byte);
73   }
74   str
75 }
76
77 #[cfg(test)]
78 mod tests {
79   use crate::{
80     establish_unpooled_connection,
81     source::password_reset_request::PasswordResetRequest_,
82     Crud,
83   };
84   use lemmy_db_schema::source::{
85     local_user::{LocalUser, LocalUserForm},
86     password_reset_request::PasswordResetRequest,
87     person::*,
88   };
89   use serial_test::serial;
90
91   #[test]
92   #[serial]
93   fn test_crud() {
94     let conn = establish_unpooled_connection();
95
96     let new_person = PersonForm {
97       name: "thommy prw".into(),
98       ..PersonForm::default()
99     };
100
101     let inserted_person = Person::create(&conn, &new_person).unwrap();
102
103     let new_local_user = LocalUserForm {
104       person_id: inserted_person.id,
105       password_encrypted: "pass".to_string(),
106       ..LocalUserForm::default()
107     };
108
109     let inserted_local_user = LocalUser::create(&conn, &new_local_user).unwrap();
110
111     let token = "nope";
112     let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
113
114     let inserted_password_reset_request =
115       PasswordResetRequest::create_token(&conn, inserted_local_user.id, token).unwrap();
116
117     let expected_password_reset_request = PasswordResetRequest {
118       id: inserted_password_reset_request.id,
119       local_user_id: inserted_local_user.id,
120       token_encrypted: token_encrypted_.to_string(),
121       published: inserted_password_reset_request.published,
122     };
123
124     let read_password_reset_request = PasswordResetRequest::read_from_token(&conn, token).unwrap();
125     let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
126
127     assert_eq!(expected_password_reset_request, read_password_reset_request);
128     assert_eq!(
129       expected_password_reset_request,
130       inserted_password_reset_request
131     );
132     assert_eq!(1, num_deleted);
133   }
134 }