]> Untitled Git - lemmy.git/blob - crates/db_views/src/registration_application_view.rs
Various pedantic clippy fixes (#2568)
[lemmy.git] / crates / db_views / src / registration_application_view.rs
1 use crate::structs::RegistrationApplicationView;
2 use diesel::{
3   dsl::count,
4   result::Error,
5   ExpressionMethods,
6   JoinOnDsl,
7   NullableExpressionMethods,
8   QueryDsl,
9 };
10 use diesel_async::RunQueryDsl;
11 use lemmy_db_schema::{
12   schema::{local_user, person, registration_application},
13   source::{
14     local_user::{LocalUser, LocalUserSettings},
15     person::{Person, PersonSafe},
16     registration_application::RegistrationApplication,
17   },
18   traits::{ToSafe, ToSafeSettings, ViewToVec},
19   utils::{get_conn, limit_and_offset, DbPool},
20 };
21 use typed_builder::TypedBuilder;
22
23 type RegistrationApplicationViewTuple = (
24   RegistrationApplication,
25   LocalUserSettings,
26   PersonSafe,
27   Option<PersonSafe>,
28 );
29
30 impl RegistrationApplicationView {
31   pub async fn read(pool: &DbPool, registration_application_id: i32) -> Result<Self, Error> {
32     let conn = &mut get_conn(pool).await?;
33     let person_alias_1 = diesel::alias!(person as person1);
34
35     let (registration_application, creator_local_user, creator, admin) =
36       registration_application::table
37         .find(registration_application_id)
38         .inner_join(
39           local_user::table.on(registration_application::local_user_id.eq(local_user::id)),
40         )
41         .inner_join(person::table.on(local_user::person_id.eq(person::id)))
42         .left_join(
43           person_alias_1
44             .on(registration_application::admin_id.eq(person_alias_1.field(person::id).nullable())),
45         )
46         .order_by(registration_application::published.desc())
47         .select((
48           registration_application::all_columns,
49           LocalUser::safe_settings_columns_tuple(),
50           Person::safe_columns_tuple(),
51           person_alias_1
52             .fields(Person::safe_columns_tuple())
53             .nullable(),
54         ))
55         .first::<RegistrationApplicationViewTuple>(conn)
56         .await?;
57
58     Ok(RegistrationApplicationView {
59       registration_application,
60       creator_local_user,
61       creator,
62       admin,
63     })
64   }
65
66   /// Returns the current unread registration_application count
67   pub async fn get_unread_count(pool: &DbPool, verified_email_only: bool) -> Result<i64, Error> {
68     let conn = &mut get_conn(pool).await?;
69     let person_alias_1 = diesel::alias!(person as person1);
70
71     let mut query = registration_application::table
72       .inner_join(local_user::table.on(registration_application::local_user_id.eq(local_user::id)))
73       .inner_join(person::table.on(local_user::person_id.eq(person::id)))
74       .left_join(
75         person_alias_1
76           .on(registration_application::admin_id.eq(person_alias_1.field(person::id).nullable())),
77       )
78       .filter(registration_application::admin_id.is_null())
79       .into_boxed();
80
81     if verified_email_only {
82       query = query.filter(local_user::email_verified.eq(true))
83     }
84
85     query
86       .select(count(registration_application::id))
87       .first::<i64>(conn)
88       .await
89   }
90 }
91
92 #[derive(TypedBuilder)]
93 #[builder(field_defaults(default))]
94 pub struct RegistrationApplicationQuery<'a> {
95   #[builder(!default)]
96   pool: &'a DbPool,
97   unread_only: Option<bool>,
98   verified_email_only: Option<bool>,
99   page: Option<i64>,
100   limit: Option<i64>,
101 }
102
103 impl<'a> RegistrationApplicationQuery<'a> {
104   pub async fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
105     let conn = &mut get_conn(self.pool).await?;
106     let person_alias_1 = diesel::alias!(person as person1);
107
108     let mut query = registration_application::table
109       .inner_join(local_user::table.on(registration_application::local_user_id.eq(local_user::id)))
110       .inner_join(person::table.on(local_user::person_id.eq(person::id)))
111       .left_join(
112         person_alias_1
113           .on(registration_application::admin_id.eq(person_alias_1.field(person::id).nullable())),
114       )
115       .order_by(registration_application::published.desc())
116       .select((
117         registration_application::all_columns,
118         LocalUser::safe_settings_columns_tuple(),
119         Person::safe_columns_tuple(),
120         person_alias_1
121           .fields(Person::safe_columns_tuple())
122           .nullable(),
123       ))
124       .into_boxed();
125
126     if self.unread_only.unwrap_or(false) {
127       query = query.filter(registration_application::admin_id.is_null())
128     }
129
130     if self.verified_email_only.unwrap_or(false) {
131       query = query.filter(local_user::email_verified.eq(true))
132     }
133
134     let (limit, offset) = limit_and_offset(self.page, self.limit)?;
135
136     query = query
137       .limit(limit)
138       .offset(offset)
139       .order_by(registration_application::published.desc());
140
141     let res = query.load::<RegistrationApplicationViewTuple>(conn).await?;
142
143     Ok(RegistrationApplicationView::from_tuple_to_vec(res))
144   }
145 }
146
147 impl ViewToVec for RegistrationApplicationView {
148   type DbTuple = RegistrationApplicationViewTuple;
149   fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
150     items
151       .into_iter()
152       .map(|a| Self {
153         registration_application: a.0,
154         creator_local_user: a.1,
155         creator: a.2,
156         admin: a.3,
157       })
158       .collect::<Vec<Self>>()
159   }
160 }
161
162 #[cfg(test)]
163 mod tests {
164   use crate::registration_application_view::{
165     RegistrationApplicationQuery,
166     RegistrationApplicationView,
167   };
168   use lemmy_db_schema::{
169     source::{
170       instance::Instance,
171       local_user::{LocalUser, LocalUserInsertForm, LocalUserSettings, LocalUserUpdateForm},
172       person::{Person, PersonInsertForm, PersonSafe},
173       registration_application::{
174         RegistrationApplication,
175         RegistrationApplicationInsertForm,
176         RegistrationApplicationUpdateForm,
177       },
178     },
179     traits::Crud,
180     utils::build_db_pool_for_tests,
181   };
182   use serial_test::serial;
183
184   #[tokio::test]
185   #[serial]
186   async fn test_crud() {
187     let pool = &build_db_pool_for_tests().await;
188
189     let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
190
191     let timmy_person_form = PersonInsertForm::builder()
192       .name("timmy_rav".into())
193       .admin(Some(true))
194       .public_key("pubkey".to_string())
195       .instance_id(inserted_instance.id)
196       .build();
197
198     let inserted_timmy_person = Person::create(pool, &timmy_person_form).await.unwrap();
199
200     let timmy_local_user_form = LocalUserInsertForm::builder()
201       .person_id(inserted_timmy_person.id)
202       .password_encrypted("nada".to_string())
203       .build();
204
205     let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
206       .await
207       .unwrap();
208
209     let sara_person_form = PersonInsertForm::builder()
210       .name("sara_rav".into())
211       .public_key("pubkey".to_string())
212       .instance_id(inserted_instance.id)
213       .build();
214
215     let inserted_sara_person = Person::create(pool, &sara_person_form).await.unwrap();
216
217     let sara_local_user_form = LocalUserInsertForm::builder()
218       .person_id(inserted_sara_person.id)
219       .password_encrypted("nada".to_string())
220       .build();
221
222     let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form)
223       .await
224       .unwrap();
225
226     // Sara creates an application
227     let sara_app_form = RegistrationApplicationInsertForm {
228       local_user_id: inserted_sara_local_user.id,
229       answer: "LET ME IIIIINN".to_string(),
230     };
231
232     let sara_app = RegistrationApplication::create(pool, &sara_app_form)
233       .await
234       .unwrap();
235
236     let read_sara_app_view = RegistrationApplicationView::read(pool, sara_app.id)
237       .await
238       .unwrap();
239
240     let jess_person_form = PersonInsertForm::builder()
241       .name("jess_rav".into())
242       .public_key("pubkey".to_string())
243       .instance_id(inserted_instance.id)
244       .build();
245
246     let inserted_jess_person = Person::create(pool, &jess_person_form).await.unwrap();
247
248     let jess_local_user_form = LocalUserInsertForm::builder()
249       .person_id(inserted_jess_person.id)
250       .password_encrypted("nada".to_string())
251       .build();
252
253     let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form)
254       .await
255       .unwrap();
256
257     // Sara creates an application
258     let jess_app_form = RegistrationApplicationInsertForm {
259       local_user_id: inserted_jess_local_user.id,
260       answer: "LET ME IIIIINN".to_string(),
261     };
262
263     let jess_app = RegistrationApplication::create(pool, &jess_app_form)
264       .await
265       .unwrap();
266
267     let read_jess_app_view = RegistrationApplicationView::read(pool, jess_app.id)
268       .await
269       .unwrap();
270
271     let mut expected_sara_app_view = RegistrationApplicationView {
272       registration_application: sara_app.clone(),
273       creator_local_user: LocalUserSettings {
274         id: inserted_sara_local_user.id,
275         person_id: inserted_sara_local_user.person_id,
276         email: inserted_sara_local_user.email,
277         show_nsfw: inserted_sara_local_user.show_nsfw,
278         theme: inserted_sara_local_user.theme,
279         default_sort_type: inserted_sara_local_user.default_sort_type,
280         default_listing_type: inserted_sara_local_user.default_listing_type,
281         interface_language: inserted_sara_local_user.interface_language,
282         show_avatars: inserted_sara_local_user.show_avatars,
283         send_notifications_to_email: inserted_sara_local_user.send_notifications_to_email,
284         validator_time: inserted_sara_local_user.validator_time,
285         show_bot_accounts: inserted_sara_local_user.show_bot_accounts,
286         show_scores: inserted_sara_local_user.show_scores,
287         show_read_posts: inserted_sara_local_user.show_read_posts,
288         show_new_post_notifs: inserted_sara_local_user.show_new_post_notifs,
289         email_verified: inserted_sara_local_user.email_verified,
290         accepted_application: inserted_sara_local_user.accepted_application,
291       },
292       creator: PersonSafe {
293         id: inserted_sara_person.id,
294         name: inserted_sara_person.name.clone(),
295         display_name: None,
296         published: inserted_sara_person.published,
297         avatar: None,
298         actor_id: inserted_sara_person.actor_id.clone(),
299         local: true,
300         banned: false,
301         ban_expires: None,
302         deleted: false,
303         admin: false,
304         bot_account: false,
305         bio: None,
306         banner: None,
307         updated: None,
308         inbox_url: inserted_sara_person.inbox_url.clone(),
309         shared_inbox_url: None,
310         matrix_user_id: None,
311         instance_id: inserted_instance.id,
312       },
313       admin: None,
314     };
315
316     assert_eq!(read_sara_app_view, expected_sara_app_view);
317
318     // Do a batch read of the applications
319     let apps = RegistrationApplicationQuery::builder()
320       .pool(pool)
321       .unread_only(Some(true))
322       .build()
323       .list()
324       .await
325       .unwrap();
326
327     assert_eq!(
328       apps,
329       [read_jess_app_view.clone(), expected_sara_app_view.clone()]
330     );
331
332     // Make sure the counts are correct
333     let unread_count = RegistrationApplicationView::get_unread_count(pool, false)
334       .await
335       .unwrap();
336     assert_eq!(unread_count, 2);
337
338     // Approve the application
339     let approve_form = RegistrationApplicationUpdateForm {
340       admin_id: Some(Some(inserted_timmy_person.id)),
341       deny_reason: None,
342     };
343
344     RegistrationApplication::update(pool, sara_app.id, &approve_form)
345       .await
346       .unwrap();
347
348     // Update the local_user row
349     let approve_local_user_form = LocalUserUpdateForm::builder()
350       .accepted_application(Some(true))
351       .build();
352
353     LocalUser::update(pool, inserted_sara_local_user.id, &approve_local_user_form)
354       .await
355       .unwrap();
356
357     let read_sara_app_view_after_approve = RegistrationApplicationView::read(pool, sara_app.id)
358       .await
359       .unwrap();
360
361     // Make sure the columns changed
362     expected_sara_app_view
363       .creator_local_user
364       .accepted_application = true;
365     expected_sara_app_view.registration_application.admin_id = Some(inserted_timmy_person.id);
366
367     expected_sara_app_view.admin = Some(PersonSafe {
368       id: inserted_timmy_person.id,
369       name: inserted_timmy_person.name.clone(),
370       display_name: None,
371       published: inserted_timmy_person.published,
372       avatar: None,
373       actor_id: inserted_timmy_person.actor_id.clone(),
374       local: true,
375       banned: false,
376       ban_expires: None,
377       deleted: false,
378       admin: true,
379       bot_account: false,
380       bio: None,
381       banner: None,
382       updated: None,
383       inbox_url: inserted_timmy_person.inbox_url.clone(),
384       shared_inbox_url: None,
385       matrix_user_id: None,
386       instance_id: inserted_instance.id,
387     });
388     assert_eq!(read_sara_app_view_after_approve, expected_sara_app_view);
389
390     // Do a batch read of apps again
391     // It should show only jessicas which is unresolved
392     let apps_after_resolve = RegistrationApplicationQuery::builder()
393       .pool(pool)
394       .unread_only(Some(true))
395       .build()
396       .list()
397       .await
398       .unwrap();
399     assert_eq!(apps_after_resolve, vec![read_jess_app_view]);
400
401     // Make sure the counts are correct
402     let unread_count_after_approve = RegistrationApplicationView::get_unread_count(pool, false)
403       .await
404       .unwrap();
405     assert_eq!(unread_count_after_approve, 1);
406
407     // Make sure the not undenied_only has all the apps
408     let all_apps = RegistrationApplicationQuery::builder()
409       .pool(pool)
410       .build()
411       .list()
412       .await
413       .unwrap();
414     assert_eq!(all_apps.len(), 2);
415
416     Person::delete(pool, inserted_timmy_person.id)
417       .await
418       .unwrap();
419     Person::delete(pool, inserted_sara_person.id).await.unwrap();
420     Person::delete(pool, inserted_jess_person.id).await.unwrap();
421     Instance::delete(pool, inserted_instance.id).await.unwrap();
422   }
423 }