]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/person.rs
f09cdfa0eef5b2dde0ce241b4e7d2544d63040c1
[lemmy.git] / crates / db_schema / src / impls / person.rs
1 use crate::{
2   functions::lower,
3   naive_now,
4   newtypes::{DbUrl, PersonId},
5   schema::person::dsl::*,
6   source::person::{Person, PersonForm},
7   traits::Crud,
8 };
9 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
10 use url::Url;
11
12 mod safe_type {
13   use crate::{schema::person::columns::*, source::person::Person, traits::ToSafe};
14
15   type Columns = (
16     id,
17     name,
18     display_name,
19     avatar,
20     banned,
21     published,
22     updated,
23     actor_id,
24     bio,
25     local,
26     banner,
27     deleted,
28     inbox_url,
29     shared_inbox_url,
30     matrix_user_id,
31     admin,
32     bot_account,
33   );
34
35   impl ToSafe for Person {
36     type SafeColumns = Columns;
37     fn safe_columns_tuple() -> Self::SafeColumns {
38       (
39         id,
40         name,
41         display_name,
42         avatar,
43         banned,
44         published,
45         updated,
46         actor_id,
47         bio,
48         local,
49         banner,
50         deleted,
51         inbox_url,
52         shared_inbox_url,
53         matrix_user_id,
54         admin,
55         bot_account,
56       )
57     }
58   }
59 }
60
61 mod safe_type_alias_1 {
62   use crate::{schema::person_alias_1::columns::*, source::person::PersonAlias1, traits::ToSafe};
63
64   type Columns = (
65     id,
66     name,
67     display_name,
68     avatar,
69     banned,
70     published,
71     updated,
72     actor_id,
73     bio,
74     local,
75     banner,
76     deleted,
77     inbox_url,
78     shared_inbox_url,
79     matrix_user_id,
80     admin,
81     bot_account,
82   );
83
84   impl ToSafe for PersonAlias1 {
85     type SafeColumns = Columns;
86     fn safe_columns_tuple() -> Self::SafeColumns {
87       (
88         id,
89         name,
90         display_name,
91         avatar,
92         banned,
93         published,
94         updated,
95         actor_id,
96         bio,
97         local,
98         banner,
99         deleted,
100         inbox_url,
101         shared_inbox_url,
102         matrix_user_id,
103         admin,
104         bot_account,
105       )
106     }
107   }
108 }
109
110 mod safe_type_alias_2 {
111   use crate::{schema::person_alias_2::columns::*, source::person::PersonAlias2, traits::ToSafe};
112
113   type Columns = (
114     id,
115     name,
116     display_name,
117     avatar,
118     banned,
119     published,
120     updated,
121     actor_id,
122     bio,
123     local,
124     banner,
125     deleted,
126     inbox_url,
127     shared_inbox_url,
128     matrix_user_id,
129     admin,
130     bot_account,
131   );
132
133   impl ToSafe for PersonAlias2 {
134     type SafeColumns = Columns;
135     fn safe_columns_tuple() -> Self::SafeColumns {
136       (
137         id,
138         name,
139         display_name,
140         avatar,
141         banned,
142         published,
143         updated,
144         actor_id,
145         bio,
146         local,
147         banner,
148         deleted,
149         inbox_url,
150         shared_inbox_url,
151         matrix_user_id,
152         admin,
153         bot_account,
154       )
155     }
156   }
157 }
158
159 impl Crud for Person {
160   type Form = PersonForm;
161   type IdType = PersonId;
162   fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
163     person
164       .filter(deleted.eq(false))
165       .find(person_id)
166       .first::<Self>(conn)
167   }
168   fn delete(conn: &PgConnection, person_id: PersonId) -> Result<usize, Error> {
169     diesel::delete(person.find(person_id)).execute(conn)
170   }
171   fn create(conn: &PgConnection, form: &PersonForm) -> Result<Self, Error> {
172     insert_into(person).values(form).get_result::<Self>(conn)
173   }
174   fn update(conn: &PgConnection, person_id: PersonId, form: &PersonForm) -> Result<Self, Error> {
175     diesel::update(person.find(person_id))
176       .set(form)
177       .get_result::<Self>(conn)
178   }
179 }
180
181 impl Person {
182   pub fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result<Self, Error> {
183     diesel::update(person.find(person_id))
184       .set(banned.eq(ban))
185       .get_result::<Self>(conn)
186   }
187
188   pub fn add_admin(conn: &PgConnection, person_id: PersonId, added: bool) -> Result<Self, Error> {
189     diesel::update(person.find(person_id))
190       .set(admin.eq(added))
191       .get_result::<Self>(conn)
192   }
193
194   pub fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
195     person
196       .filter(deleted.eq(false))
197       .filter(local.eq(true))
198       .filter(lower(name).eq(lower(from_name)))
199       .first::<Person>(conn)
200   }
201
202   pub fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
203     diesel::update(person.find(person_id))
204       .set((last_refreshed_at.eq(naive_now()),))
205       .get_result::<Self>(conn)
206   }
207
208   pub fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
209     use crate::schema::local_user;
210
211     // Set the local user info to none
212     diesel::update(local_user::table.filter(local_user::person_id.eq(person_id)))
213       .set((
214         local_user::email.eq::<Option<String>>(None),
215         local_user::validator_time.eq(naive_now()),
216       ))
217       .execute(conn)?;
218
219     diesel::update(person.find(person_id))
220       .set((
221         display_name.eq::<Option<String>>(None),
222         bio.eq::<Option<String>>(None),
223         matrix_user_id.eq::<Option<String>>(None),
224         deleted.eq(true),
225         updated.eq(naive_now()),
226       ))
227       .get_result::<Self>(conn)
228   }
229
230   pub fn upsert(conn: &PgConnection, person_form: &PersonForm) -> Result<Person, Error> {
231     insert_into(person)
232       .values(person_form)
233       .on_conflict(actor_id)
234       .do_update()
235       .set(person_form)
236       .get_result::<Self>(conn)
237   }
238
239   pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
240     use crate::schema::person::dsl::*;
241     let object_id: DbUrl = object_id.into();
242     Ok(
243       person
244         .filter(deleted.eq(false))
245         .filter(actor_id.eq(object_id))
246         .first::<Person>(conn)
247         .ok()
248         .map(Into::into),
249     )
250   }
251
252   pub fn update_deleted(
253     conn: &PgConnection,
254     person_id: PersonId,
255     new_deleted: bool,
256   ) -> Result<Person, Error> {
257     use crate::schema::person::dsl::*;
258     diesel::update(person.find(person_id))
259       .set(deleted.eq(new_deleted))
260       .get_result::<Self>(conn)
261   }
262 }
263
264 #[cfg(test)]
265 mod tests {
266   use crate::{establish_unpooled_connection, source::person::*, traits::Crud};
267
268   #[test]
269   fn test_crud() {
270     let conn = establish_unpooled_connection();
271
272     let new_person = PersonForm {
273       name: "holly".into(),
274       public_key: "nada".to_owned(),
275       ..PersonForm::default()
276     };
277
278     let inserted_person = Person::create(&conn, &new_person).unwrap();
279
280     let expected_person = Person {
281       id: inserted_person.id,
282       name: "holly".into(),
283       display_name: None,
284       avatar: None,
285       banner: None,
286       banned: false,
287       deleted: false,
288       published: inserted_person.published,
289       updated: None,
290       actor_id: inserted_person.actor_id.to_owned(),
291       bio: None,
292       local: true,
293       bot_account: false,
294       admin: false,
295       private_key: None,
296       public_key: "nada".to_owned(),
297       last_refreshed_at: inserted_person.published,
298       inbox_url: inserted_person.inbox_url.to_owned(),
299       shared_inbox_url: None,
300       matrix_user_id: None,
301     };
302
303     let read_person = Person::read(&conn, inserted_person.id).unwrap();
304     let updated_person = Person::update(&conn, inserted_person.id, &new_person).unwrap();
305     let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
306
307     assert_eq!(expected_person, read_person);
308     assert_eq!(expected_person, inserted_person);
309     assert_eq!(expected_person, updated_person);
310     assert_eq!(1, num_deleted);
311   }
312 }