]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/local_user.rs
Add diesel_async, get rid of blocking function (#2510)
[lemmy.git] / crates / db_schema / src / impls / local_user.rs
1 use crate::{
2   newtypes::LocalUserId,
3   schema::local_user::dsl::*,
4   source::{
5     actor_language::{LocalUserLanguage, SiteLanguage},
6     local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
7   },
8   traits::Crud,
9   utils::{get_conn, naive_now, DbPool},
10 };
11 use bcrypt::{hash, DEFAULT_COST};
12 use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
13 use diesel_async::RunQueryDsl;
14
15 mod safe_settings_type {
16   use crate::{
17     schema::local_user::columns::*,
18     source::local_user::LocalUser,
19     traits::ToSafeSettings,
20   };
21
22   type Columns = (
23     id,
24     person_id,
25     email,
26     show_nsfw,
27     theme,
28     default_sort_type,
29     default_listing_type,
30     interface_language,
31     show_avatars,
32     send_notifications_to_email,
33     validator_time,
34     show_bot_accounts,
35     show_scores,
36     show_read_posts,
37     show_new_post_notifs,
38     email_verified,
39     accepted_application,
40   );
41
42   impl ToSafeSettings for LocalUser {
43     type SafeSettingsColumns = Columns;
44
45     /// Includes everything but the hashed password
46     fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
47       (
48         id,
49         person_id,
50         email,
51         show_nsfw,
52         theme,
53         default_sort_type,
54         default_listing_type,
55         interface_language,
56         show_avatars,
57         send_notifications_to_email,
58         validator_time,
59         show_bot_accounts,
60         show_scores,
61         show_read_posts,
62         show_new_post_notifs,
63         email_verified,
64         accepted_application,
65       )
66     }
67   }
68 }
69
70 impl LocalUser {
71   pub async fn update_password(
72     pool: &DbPool,
73     local_user_id: LocalUserId,
74     new_password: &str,
75   ) -> Result<Self, Error> {
76     let conn = &mut get_conn(pool).await?;
77     let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
78
79     diesel::update(local_user.find(local_user_id))
80       .set((
81         password_encrypted.eq(password_hash),
82         validator_time.eq(naive_now()),
83       ))
84       .get_result::<Self>(conn)
85       .await
86   }
87
88   pub async fn set_all_users_email_verified(pool: &DbPool) -> Result<Vec<Self>, Error> {
89     let conn = &mut get_conn(pool).await?;
90     diesel::update(local_user)
91       .set(email_verified.eq(true))
92       .get_results::<Self>(conn)
93       .await
94   }
95
96   pub async fn set_all_users_registration_applications_accepted(
97     pool: &DbPool,
98   ) -> Result<Vec<Self>, Error> {
99     let conn = &mut get_conn(pool).await?;
100     diesel::update(local_user)
101       .set(accepted_application.eq(true))
102       .get_results::<Self>(conn)
103       .await
104   }
105 }
106
107 #[async_trait]
108 impl Crud for LocalUser {
109   type InsertForm = LocalUserInsertForm;
110   type UpdateForm = LocalUserUpdateForm;
111   type IdType = LocalUserId;
112   async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
113     let conn = &mut get_conn(pool).await?;
114     local_user.find(local_user_id).first::<Self>(conn).await
115   }
116   async fn delete(pool: &DbPool, local_user_id: LocalUserId) -> Result<usize, Error> {
117     let conn = &mut get_conn(pool).await?;
118     diesel::delete(local_user.find(local_user_id))
119       .execute(conn)
120       .await
121   }
122   async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
123     let conn = &mut get_conn(pool).await?;
124     let mut form_with_encrypted_password = form.clone();
125     let password_hash =
126       hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
127     form_with_encrypted_password.password_encrypted = password_hash;
128
129     let local_user_ = insert_into(local_user)
130       .values(form_with_encrypted_password)
131       .get_result::<Self>(conn)
132       .await
133       .expect("couldnt create local user");
134
135     let site_languages = SiteLanguage::read_local(pool).await;
136     if let Ok(langs) = site_languages {
137       // if site exists, init user with site languages
138       LocalUserLanguage::update(pool, langs, local_user_.id).await?;
139     } else {
140       // otherwise, init with all languages (this only happens during tests and
141       // for first admin user, which is created before site)
142       LocalUserLanguage::update(pool, vec![], local_user_.id).await?;
143     }
144
145     Ok(local_user_)
146   }
147   async fn update(
148     pool: &DbPool,
149     local_user_id: LocalUserId,
150     form: &Self::UpdateForm,
151   ) -> Result<Self, Error> {
152     let conn = &mut get_conn(pool).await?;
153     diesel::update(local_user.find(local_user_id))
154       .set(form)
155       .get_result::<Self>(conn)
156       .await
157   }
158 }