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